// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_histo_base_histo #define tools_histo_base_histo #include "histo_data" #include #include //for annotations #include namespace tools { namespace histo { //TC is for a coordinate. //TO is for an offset used to identify a bin. //TN is for a number of entries. //TW is for a weight. //TH is for a height. template class base_histo : protected histo_data { typedef histo_data parent; private: static const std::string& s_class() { static const std::string s_v("tools::histo::base_histo"); return s_v; } public: typedef histo_data hd_t; typedef axis axis_t; typedef typename axis_t::bn_t bn_t; typedef unsigned int dim_t; typedef TC coordinate_t; typedef TO offset_t; typedef TN num_entries_t; typedef TW weight_t; typedef TH height_t; protected: virtual TH get_bin_height(TO) const = 0; //histo/profile protected: void base_from_data(const hd_t& a_from) {parent::operator=(a_from);} hd_t base_get_data() const { hd_t hd; hd = *this; return hd; } public: const hd_t& dac() const {return *this;} //data accessor. protected: base_histo():parent() { } protected: virtual ~base_histo() { } protected: base_histo(const base_histo& a_from):parent(a_from) { } base_histo& operator=(const base_histo& a_from) { if(&a_from==this) return *this; parent::operator=(a_from); return *this; } public: bool equals(const base_histo& a_from,const TW& a_prec,TW(*a_fabs)(TW)) const { return parent::equals(a_from,a_prec,a_fabs); } const std::string& title() const {return parent::m_title;} bool set_title(const std::string& a_title){parent::m_title = a_title;return true;} dim_t dimension() const {return parent::m_dimension;} dim_t number_of_planes() const {return dim_planes(parent::m_dimension);} TN entries() const { return parent::m_in_range_entries; //not set if reading a TH from a CERN-ROOT file. } TN all_entries() const { return parent::m_all_entries; //works also is reading histo from a CERN-ROOT file. } TN extra_entries() const { return parent::m_all_entries-parent::m_in_range_entries; //works also is reading histo from a CERN-ROOT file. } TW equivalent_bin_entries() const { TW sw = 0; TW sw2 = 0; for(TO ibin=0;ibin=value) value = vbin; } } } return value; } bool min_bin_height_with_entries(TH& a_value) const { TH value = 0; bool first = true; for(TO ibin=0;ibin0) ) { TH vbin = get_bin_height(ibin); if(first) { first = false; value = vbin; } else { if(vbin<=value) value = vbin; } } } a_value = value; return first?false:true; //return true if at least one bin with entries processed. } bool max_bin_height_with_entries(TH& a_value) const { TH value = 0; bool first = true; for(TO ibin=0;ibin0) ) { TH vbin = get_bin_height(ibin); if(first) { first = false; value = vbin; } else { if(vbin>=value) value = vbin; } } } a_value = value; return first?false:true; //return true if at least one bin with entries processed. } bool has_entries_per_bin() const { //to detect histos coming from TH streaming out of a root file. // it assumes that update_fast_getters() had been applied. if(parent::m_in_range_entries) return true; // may be a from-root histo : if(parent::m_in_range_Sw) return false; // no in range entries and weight : return true; //for exa not filled = ok. } public: //histo_data bool get_ith_axis_Sxw(dim_t a_axis,TC& a_value) const { a_value = 0; if(a_axis>=parent::m_dimension) return false; for(TO ibin=0;ibin=parent::m_dimension) return false; for(TO ibin=0;ibin& aNumbers, const std::vector& aMins, const std::vector& aMaxs) { // Clear : parent::m_bin_entries.clear(); parent::m_bin_Sw.clear(); parent::m_bin_Sw2.clear(); parent::m_bin_Sxw.clear(); parent::m_bin_Sx2w.clear(); parent::m_in_range_Sxw.clear(); parent::m_in_range_Sx2w.clear(); parent::m_axes.clear(); parent::m_in_range_plane_Sxyw.clear(); parent::m_annotations.clear(); parent::m_bin_number = 0; parent::m_dimension = 0; parent::m_all_entries = 0; parent::m_in_range_entries = 0; parent::m_in_range_Sw = 0; parent::m_in_range_Sw2 = 0; parent::m_in_range_Sxw.resize(a_dim,0); parent::m_in_range_Sx2w.resize(a_dim,0); // Some checks : if(!a_dim) return false; parent::m_axes.resize(a_dim); // Setup axes : for(dim_t iaxis=0;iaxis >& a_edges) { // Clear : parent::m_bin_entries.clear(); parent::m_bin_Sw.clear(); parent::m_bin_Sw2.clear(); parent::m_bin_Sxw.clear(); parent::m_bin_Sx2w.clear(); parent::m_in_range_Sxw.clear(); parent::m_in_range_Sx2w.clear(); parent::m_axes.clear(); parent::m_in_range_plane_Sxyw.clear(); parent::m_annotations.clear(); parent::m_bin_number = 0; parent::m_dimension = 0; parent::m_all_entries = 0; parent::m_in_range_entries = 0; parent::m_in_range_Sw = 0; parent::m_in_range_Sw2 = 0; parent::m_in_range_Sxw.resize(a_dim,0); parent::m_in_range_Sx2w.resize(a_dim,0); // Some checks : if(!a_dim) return false; parent::m_axes.resize(a_dim); // Setup axes : for(dim_t iaxis=0;iaxis empty; empty.resize(parent::m_dimension,0); parent::m_bin_Sxw.resize(n_bin,empty); parent::m_bin_Sx2w.resize(n_bin,empty); parent::m_bin_number = n_bin; // All bins : [in-range, underflow, outflow] bins. parent::m_axes[0].m_offset = 1; for(iaxis=1;iaxis& bins_entries() const {return parent::m_bin_entries;} const std::vector& bins_sum_w() const {return parent::m_bin_Sw;} const std::vector& bins_sum_w2() const {return parent::m_bin_Sw2;} const std::vector< std::vector >& bins_sum_xw() const {return parent::m_bin_Sxw;} const std::vector< std::vector >& bins_sum_x2w() const {return parent::m_bin_Sx2w;} const std::vector& in_range_planes_xyw() const {return parent::m_in_range_plane_Sxyw;} public: const axis_t& get_axis(int a_index) const {return parent::m_axes[a_index];} offset_t get_bins() const {return parent::m_bin_number;} const std::string& get_title() const {return parent::m_title;} dim_t get_dimension() const {return parent::m_dimension;} bool is_valid() const {return (parent::m_dimension?true:false);} public: //annotations : typedef std::map annotations_t; const annotations_t& annotations() const {return parent::m_annotations;} annotations_t annotations() {return parent::m_annotations;} void add_annotation(const std::string& a_key,const std::string& a_value) { parent::m_annotations[a_key] = a_value; //override if a_key already exists. } bool annotation(const std::string& a_key,std::string& a_value) const { annotations_t::const_iterator it = parent::m_annotations.find(a_key); if(it==parent::m_annotations.end()) {a_value.clear();return false;} a_value = (*it).second; return true; } void set_annotations(const annotations_t& a_annotations) {parent::m_annotations = a_annotations;} void hprint_annotations(std::ostream& a_out) { a_out << " * ANNOTATIONS :" << std::endl; annotations_t::const_iterator it; for(it=parent::m_annotations.begin();it!=parent::m_annotations.end();++it) { a_out << " * " << (*it).first << " = " << (*it).second << std::endl; } } protected: bool is_compatible(const base_histo& a_histo){ if(parent::m_dimension!=a_histo.m_dimension) return false; for(dim_t iaxis=0;iaxis is(parent::m_dimension); for(TO ibin=0;ibin is(parent::m_dimension); for(TO ibin=0;ibin=parent::m_dimension) return false; TW sw = 0; TC sxw = 0; for(TO ibin=0;ibin=parent::m_dimension) return false; TW sw = 0; TC sxw = 0; TC sx2w = 0; for(TO ibin=0;ibin& aIs) const { if(parent::m_bin_number==0) return 0; TO offset; if(!histo::get_offset(parent::m_axes,aIs,offset)) return 0; return parent::m_bin_entries[offset]; } }; // predefined annotation keys : inline const std::string& key_axis_x_title() { static const std::string s_v("axis_x.title"); return s_v; } inline const std::string& key_axis_y_title() { static const std::string s_v("axis_y.title"); return s_v; } inline const std::string& key_axis_z_title() { static const std::string s_v("axis_z.title"); return s_v; } }} #endif