// 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 #ifdef TOOLS_MEM #include "../mem" #endif #include "histo_data" #include #include //for annotations namespace tools { namespace histo { //TC is for a coordinate. //TN is for a number of entries. //TW is for a weight. //TH is for a height. template class base_histo { static const std::string& s_class() { static const std::string s_v("tools::histo::base_histo"); return s_v; } public: typedef typename axis::bn_t bn_t; typedef unsigned int dim_t; protected: virtual TH get_bin_height(int) const = 0; //histo/profile protected: void base_from_data(const histo_data& a_from) { m_title = a_from.m_title; m_dimension = a_from.m_dimension; m_bin_number = a_from.m_bin_number; // Arrays : m_bin_entries = a_from.m_bin_entries; m_bin_Sw = a_from.m_bin_Sw; m_bin_Sw2 = a_from.m_bin_Sw2; m_bin_Sxw = a_from.m_bin_Sxw; m_bin_Sx2w = a_from.m_bin_Sx2w; m_axes = a_from.m_axes; m_annotations = a_from.m_annotations; } histo_data base_get_data() const { histo_data hd; hd.m_title = m_title; hd.m_dimension = m_dimension; hd.m_bin_number = m_bin_number; // Arrays : hd.m_bin_entries = m_bin_entries; hd.m_bin_Sw = m_bin_Sw; hd.m_bin_Sw2 = m_bin_Sw2; hd.m_bin_Sxw = m_bin_Sxw; hd.m_bin_Sx2w = m_bin_Sx2w; hd.m_axes = m_axes; hd.m_annotations = m_annotations; return hd; } protected: base_histo() :m_dimension(0) ,m_bin_number(0) { #ifdef TOOLS_MEM mem::increment(s_class().c_str()); #endif } protected: virtual ~base_histo(){ #ifdef TOOLS_MEM mem::decrement(s_class().c_str()); #endif } protected: base_histo(const base_histo& a_from) :m_title(a_from.m_title) ,m_dimension(a_from.m_dimension) ,m_bin_number(a_from.m_bin_number) // Arrays : ,m_bin_entries(a_from.m_bin_entries) ,m_bin_Sw(a_from.m_bin_Sw) ,m_bin_Sw2(a_from.m_bin_Sw2) ,m_bin_Sxw(a_from.m_bin_Sxw) ,m_bin_Sx2w(a_from.m_bin_Sx2w) ,m_axes(a_from.m_axes) ,m_annotations(a_from.m_annotations) { #ifdef TOOLS_MEM mem::increment(s_class().c_str()); #endif } base_histo& operator=(const base_histo& a_from) { m_title = a_from.m_title; m_dimension = a_from.m_dimension; m_bin_number = a_from.m_bin_number; // Arrays : m_bin_entries = a_from.m_bin_entries; m_bin_Sw = a_from.m_bin_Sw; m_bin_Sw2 = a_from.m_bin_Sw2; m_bin_Sxw = a_from.m_bin_Sxw; m_bin_Sx2w = a_from.m_bin_Sx2w; m_axes = a_from.m_axes; m_annotations = a_from.m_annotations; return *this; } public: const std::string& title() const {return m_title;} std::string title() {return m_title;} bool set_title(const std::string& a_title){m_title = a_title;return true;} dim_t dimension() const {return m_dimension;} TN entries() const { return get_entries();} TN all_entries() const { TN number = 0; for(bn_t ibin=0;ibin=value) value = vbin; } } } return value; } protected: enum {AxisX=0,AxisY=1,AxisZ=2}; bool configure(dim_t a_dim, const std::vector& aNumbers, const std::vector& aMins, const std::vector& aMaxs) { // Clear : m_bin_entries.clear(); m_bin_Sw.clear(); m_bin_Sw2.clear(); m_bin_Sxw.clear(); m_bin_Sx2w.clear(); m_axes.clear(); m_bin_number = 0; m_dimension = 0; m_annotations.clear(); // Some checks : if(!a_dim) return false; m_axes.resize(a_dim); // Setup axes : for(dim_t iaxis=0;iaxis >& aEdges) { // Clear : m_bin_entries.clear(); m_bin_Sw.clear(); m_bin_Sw2.clear(); m_bin_Sxw.clear(); m_bin_Sx2w.clear(); m_axes.clear(); m_bin_number = 0; m_dimension = 0; m_annotations.clear(); // Some checks : if(!a_dim) return false; m_axes.resize(a_dim); // Setup axes : for(dim_t iaxis=0;iaxis empty; empty.resize(m_dimension,0); m_bin_Sxw.resize(n_bin,empty); m_bin_Sx2w.resize(n_bin,empty); m_bin_number = n_bin; // All bins : [in-range, underflow, outflow] bins. m_axes[0].m_offset = 1; for(iaxis=1;iaxis=m_dimension) return false; for(bn_t ibin=0;ibin=m_dimension) return false; for(bn_t ibin=0;ibin& aIs) const { int offset = aOffset; {for(int iaxis=m_dimension-1;iaxis>=0;iaxis--) { aIs[iaxis] = offset/m_axes[iaxis].m_offset; offset -= aIs[iaxis] * m_axes[iaxis].m_offset; }} for(unsigned iaxis=0;iaxis::UNDERFLOW_BIN; } else if(aIs[iaxis]==int(m_axes[iaxis].m_number_of_bins+1)) { aIs[iaxis] = axis::OVERFLOW_BIN; } else { aIs[iaxis]--; } } } bool is_out(bn_t aOffset) const { int offset = aOffset; int index; for(int iaxis=m_dimension-1;iaxis>=0;iaxis--) { index = offset/m_axes[iaxis].m_offset; if(index==0) return true; if(index==(int(m_axes[iaxis].m_number_of_bins)+1)) return true; offset -= index * m_axes[iaxis].m_offset; } return false; } bool get_offset(const std::vector& aIs,bn_t& a_offset) const { // aIs[iaxis] is given in in-range indexing : // - [0,n[iaxis]-1] for in-range bins // - UNDERFLOW_BIN for the iaxis underflow bin // - OVERFLOW_BIN for the iaxis overflow bin a_offset = 0; if(!m_dimension) return false; bn_t ibin; for(dim_t iaxis=0;iaxis& bins_entries() const {return m_bin_entries;} const std::vector& bins_sum_w() const {return m_bin_Sw;} const std::vector& bins_sum_w2() const {return m_bin_Sw2;} const std::vector< std::vector >& bins_sum_xw() const {return m_bin_Sxw;} const std::vector< std::vector >& bins_sum_x2w() const {return m_bin_Sx2w;} public: const axis& get_axis(int aIndex) const {return m_axes[aIndex];} bn_t get_bins() const {return m_bin_number;} const std::string& get_title() const {return m_title;} dim_t get_dimension() const {return m_dimension;} bool is_valid() const {return (m_dimension?true:false);} public: //annotations : typedef std::map annotations_t; const annotations_t& annotations() const {return m_annotations;} annotations_t annotations() {return m_annotations;} void add_annotation(const std::string& a_key,const std::string& a_value) { 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 = m_annotations.find(a_key); if(it==m_annotations.end()) {a_value.clear();return false;} a_value = (*it).second; return true; } protected: bool is_compatible(const base_histo& a_histo){ if(m_dimension!=a_histo.m_dimension) return false; for(dim_t iaxis=0;iaxis is(m_dimension); for(bn_t ibin=0;ibin is(m_dimension); for(bn_t ibin=0;ibin=m_dimension) return false; TW sw = 0; TC sxw = 0; for(bn_t ibin=0;ibin=m_dimension) return false; TW sw = 0; TC sxw = 0; TC sx2w = 0; for(bn_t ibin=0;ibin& aIs) const { if(m_bin_number==0) return 0; bn_t offset; if(!get_offset(aIs,offset)) return 0; return m_bin_entries[offset]; } protected: // General : std::string m_title; dim_t m_dimension; // Bins : bn_t m_bin_number; std::vector m_bin_entries; std::vector m_bin_Sw; std::vector m_bin_Sw2; std::vector< std::vector > m_bin_Sxw; std::vector< std::vector > m_bin_Sx2w; // Axes : std::vector< axis > m_axes; // etc : annotations_t m_annotations; }; // 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