Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/histo/base_histo is written in an unsupported language. File is not indexed.

0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003 
0004 #ifndef tools_histo_base_histo
0005 #define tools_histo_base_histo
0006 
0007 #ifdef TOOLS_MEM
0008 #include "../mem"
0009 #endif
0010 
0011 #include "histo_data"
0012 
0013 #include <cmath>
0014 #include <map> //for annotations
0015 #include <ostream>
0016 
0017 namespace tools {
0018 namespace histo {
0019 
0020 //TC is for a coordinate.
0021 //TO is for an offset used to identify a bin.
0022 //TN is for a number of entries.
0023 //TW is for a weight.
0024 //TH is for a height.
0025 
0026 template <class TC,class TO,class TN,class TW,class TH>
0027 class base_histo : protected histo_data<TC,TO,TN,TW> {
0028   typedef histo_data<TC,TO,TN,TW> parent;
0029 private:
0030   static const std::string& s_class() {
0031     static const std::string s_v("tools::histo::base_histo");
0032     return s_v;
0033   }
0034 public:
0035   typedef histo_data<TC,TO,TN,TW> hd_t;
0036   typedef axis<TC,TO> axis_t;
0037   typedef typename axis_t::bn_t bn_t;
0038   typedef unsigned int dim_t;
0039   typedef TC coordinate_t;
0040   typedef TO offset_t;
0041   typedef TN num_entries_t;
0042   typedef TW weight_t;
0043   typedef TH height_t;
0044 protected:
0045   virtual TH get_bin_height(TO) const = 0;  //histo/profile
0046 protected:
0047   void base_from_data(const hd_t& a_from) {parent::operator=(a_from);}
0048 #ifdef tools_histo_base_histo //for backward compatibility with tools
0049   hd_t base_get_data() const {
0050     hd_t hd;
0051     hd = *this;
0052     return hd;
0053   }
0054 #endif
0055 public:
0056   const hd_t& dac() const {return *this;} //data accessor.
0057 protected:
0058   base_histo():parent() {
0059 #ifdef TOOLS_MEM
0060     mem::increment(s_class().c_str());
0061 #endif
0062   }
0063 protected:
0064   virtual ~base_histo() {
0065 #ifdef TOOLS_MEM
0066     mem::decrement(s_class().c_str());
0067 #endif
0068   }
0069 protected:
0070   base_histo(const base_histo& a_from):parent(a_from) {
0071 #ifdef TOOLS_MEM
0072     mem::increment(s_class().c_str());
0073 #endif
0074   }
0075 
0076   base_histo& operator=(const base_histo& a_from) {
0077     if(&a_from==this) return *this;
0078     parent::operator=(a_from);
0079     return *this;
0080   }
0081 
0082 public:
0083   bool equals(const base_histo& a_from,const TW& a_prec,TW(*a_fabs)(TW)) const {
0084     return parent::equals(a_from,a_prec,a_fabs);
0085   }
0086 
0087   const std::string& title() const {return parent::m_title;}
0088   bool set_title(const std::string& a_title){parent::m_title = a_title;return true;}
0089   dim_t dimension() const {return parent::m_dimension;}
0090   dim_t number_of_planes() const {return dim_planes(parent::m_dimension);}
0091 
0092   TN entries() const {
0093     return parent::m_in_range_entries; //not set if reading a TH from a CERN-ROOT file.
0094   }
0095   TN all_entries() const {
0096     return parent::m_all_entries; //works also is reading histo from a CERN-ROOT file.
0097   }
0098 
0099   TN extra_entries() const {
0100     return parent::m_all_entries-parent::m_in_range_entries; //works also is reading histo from a CERN-ROOT file.
0101   }
0102   TW equivalent_bin_entries() const {
0103     TW sw = 0;
0104     TW sw2 = 0;
0105     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0106       if(!histo::is_out(parent::m_axes,ibin)) {
0107         sw += parent::m_bin_Sw[ibin];
0108         sw2 += parent::m_bin_Sw2[ibin];
0109       }
0110     }
0111     if(sw2==0) return 0;
0112     return (sw * sw)/sw2;
0113   }
0114   TH sum_bin_heights() const {
0115     TH sh = 0;
0116     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0117       if(!histo::is_out(parent::m_axes,ibin)) {
0118         sh += get_bin_height(ibin);
0119       }
0120     }
0121     return sh;
0122   }
0123   TH sum_all_bin_heights() const {
0124     TH sh = 0;
0125     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0126       sh += get_bin_height(ibin);
0127     }
0128     return sh;
0129   }
0130 
0131   TH sum_extra_bin_heights() const {
0132     TH sh = 0;
0133     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0134       if(histo::is_out(parent::m_axes,ibin)) {
0135         sh += get_bin_height(ibin);
0136       }
0137     }
0138     return sh;
0139   }
0140 
0141   TH min_bin_height() const {
0142     TH value = 0;
0143     bool first = true;
0144     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0145       if(!histo::is_out(parent::m_axes,ibin)) {
0146         TH vbin = get_bin_height(ibin);
0147         if(first) {
0148           first = false;
0149           value = vbin;
0150         } else {
0151           if(vbin<=value) value = vbin;
0152         }
0153       }
0154     }
0155     return value;
0156   }
0157 
0158   TH max_bin_height() const {
0159     TH value = 0;
0160     bool first = true;
0161     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0162       if(!histo::is_out(parent::m_axes,ibin)) {
0163         TH vbin = get_bin_height(ibin);
0164         if(first) {
0165           first = false;
0166           value = vbin;
0167         } else {
0168           if(vbin>=value) value = vbin;
0169         }
0170       }
0171     }
0172     return value;
0173   }
0174 
0175   bool min_bin_height_with_entries(TH& a_value) const {
0176     TH value = 0;
0177     bool first = true;
0178     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0179       if(!histo::is_out(parent::m_axes,ibin) && (parent::m_bin_entries[ibin]>0) ) {
0180         TH vbin = get_bin_height(ibin);
0181         if(first) {
0182           first = false;
0183           value = vbin;
0184         } else {
0185           if(vbin<=value) value = vbin;
0186         }
0187       }
0188     }
0189     a_value = value;
0190     return first?false:true; //return true if at least one bin with entries processed.
0191   }
0192 
0193   bool max_bin_height_with_entries(TH& a_value) const {
0194     TH value = 0;
0195     bool first = true;
0196     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0197       if(!histo::is_out(parent::m_axes,ibin) && (parent::m_bin_entries[ibin]>0) ) {
0198         TH vbin = get_bin_height(ibin);
0199         if(first) {
0200           first = false;
0201           value = vbin;
0202         } else {
0203           if(vbin>=value) value = vbin;
0204         }
0205       }
0206     }
0207     a_value = value;
0208     return first?false:true; //return true if at least one bin with entries processed.
0209   }
0210 
0211   bool has_entries_per_bin() const { //to detect histos coming from TH streaming out of a root file.
0212     // it assumes that update_fast_getters() had been applied.
0213     if(parent::m_in_range_entries) return true;
0214     // may be a from-root histo :
0215     if(parent::m_in_range_Sw) return false;
0216     // no in range entries and weight :
0217     return true; //for exa not filled = ok.
0218   }
0219 
0220 public: //histo_data
0221   bool get_ith_axis_Sxw(dim_t a_axis,TC& a_value) const {
0222     a_value = 0;
0223     if(a_axis>=parent::m_dimension) return false;
0224     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0225       if(!histo::is_out(parent::m_axes,ibin)) {
0226         a_value += parent::m_bin_Sxw[ibin][a_axis];
0227       }
0228     }
0229     return true;
0230   }
0231 
0232   bool get_ith_axis_Sx2w(dim_t a_axis,TC& a_value) const {
0233     a_value = 0;
0234     if(a_axis>=parent::m_dimension) return false;
0235     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0236       if(!histo::is_out(parent::m_axes,ibin)) {
0237         a_value += parent::m_bin_Sx2w[ibin][a_axis];
0238       }
0239     }
0240     return true;
0241   }
0242 
0243   TW get_in_range_Sw() const {return parent::m_in_range_Sw;}   //for CERN-ROOT file writing.
0244   TW get_in_range_Sw2() const {return parent::m_in_range_Sw2;} //for CERN-ROOT file writing.
0245 
0246   void get_Sw_Sw2(TW& a_sw,TW& a_sw2) const {
0247     a_sw = 0;
0248     a_sw2 = 0;
0249     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0250       if(!histo::is_out(parent::m_axes,ibin)) {
0251         a_sw += parent::m_bin_Sw[ibin];
0252         a_sw2 += parent::m_bin_Sw2[ibin];
0253       }
0254     }
0255   }
0256   void get_all_Sw_Sw2(TW& a_sw,TW& a_sw2) const {
0257     a_sw = 0;
0258     a_sw2 = 0;
0259     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0260       a_sw += parent::m_bin_Sw[ibin];
0261       a_sw2 += parent::m_bin_Sw2[ibin];
0262     }
0263   }
0264 
0265 /*
0266   TW get_all_Sw() const {
0267     TW sw = 0;
0268     for(TO ibin=0;ibin<m_bin_number;ibin++) sw += m_bin_Sw[ibin];
0269     return sw;
0270   }
0271   TN get_all_entries() const {
0272     TN number = 0;
0273     for(TO ibin=0;ibin<m_bin_number;ibin++) {
0274       number += m_bin_entries[ibin];
0275     }
0276     return number;
0277   }
0278 
0279   // for tools/wroot/streamers :
0280   TN get_entries() const {
0281     TN number = 0;
0282     for(TO ibin=0;ibin<m_bin_number;ibin++) {
0283       if(!histo::is_out(m_axes,ibin)) {
0284         number += m_bin_entries[ibin];
0285       }
0286     }
0287     return number;
0288   }
0289 */
0290 protected:
0291   enum {AxisX=0,AxisY=1,AxisZ=2};
0292 
0293   bool configure(dim_t a_dim,
0294                  const std::vector<bn_t>& aNumbers,
0295                  const std::vector<TC>& aMins,
0296                  const std::vector<TC>& aMaxs) {
0297     // Clear :
0298     parent::m_bin_entries.clear();
0299     parent::m_bin_Sw.clear();
0300     parent::m_bin_Sw2.clear();
0301     parent::m_bin_Sxw.clear();
0302     parent::m_bin_Sx2w.clear();
0303     parent::m_in_range_Sxw.clear();
0304     parent::m_in_range_Sx2w.clear();
0305     parent::m_axes.clear();
0306     parent::m_in_range_plane_Sxyw.clear();
0307     parent::m_annotations.clear();
0308 
0309     parent::m_bin_number = 0;
0310     parent::m_dimension = 0;
0311     parent::m_all_entries = 0;
0312     parent::m_in_range_entries = 0;
0313     parent::m_in_range_Sw = 0;
0314     parent::m_in_range_Sw2 = 0;
0315     parent::m_in_range_Sxw.resize(a_dim,0);
0316     parent::m_in_range_Sx2w.resize(a_dim,0);
0317 
0318     // Some checks :
0319     if(!a_dim) return false;
0320     parent::m_axes.resize(a_dim);
0321     // Setup axes :
0322     for(dim_t iaxis=0;iaxis<a_dim;iaxis++) {
0323       if(!parent::m_axes[iaxis].configure(aNumbers[iaxis],aMins[iaxis],aMaxs[iaxis])) {
0324         // do not do :
0325         //   m_axes.clear()
0326         // so that :
0327         //   b1::axis(),b2::axis_[x,y]()
0328         // do not crash in case of a bad booking.
0329         //m_axes.clear();
0330         return false;
0331       }
0332     }
0333 
0334     parent::m_dimension = a_dim;
0335 
0336     base_allocate(); //set m_bin_number.
0337 
0338     return true;
0339   }
0340 
0341   bool configure(dim_t a_dim,const std::vector< std::vector<TC> >& a_edges) {
0342     // Clear :
0343     parent::m_bin_entries.clear();
0344     parent::m_bin_Sw.clear();
0345     parent::m_bin_Sw2.clear();
0346     parent::m_bin_Sxw.clear();
0347     parent::m_bin_Sx2w.clear();
0348     parent::m_in_range_Sxw.clear();
0349     parent::m_in_range_Sx2w.clear();
0350     parent::m_axes.clear();
0351     parent::m_in_range_plane_Sxyw.clear();
0352     parent::m_annotations.clear();
0353 
0354     parent::m_bin_number = 0;
0355     parent::m_dimension = 0;
0356     parent::m_all_entries = 0;
0357     parent::m_in_range_entries = 0;
0358     parent::m_in_range_Sw = 0;
0359     parent::m_in_range_Sw2 = 0;
0360     parent::m_in_range_Sxw.resize(a_dim,0);
0361     parent::m_in_range_Sx2w.resize(a_dim,0);
0362 
0363     // Some checks :
0364     if(!a_dim) return false;
0365     parent::m_axes.resize(a_dim);
0366     // Setup axes :
0367     for(dim_t iaxis=0;iaxis<a_dim;iaxis++) {
0368       if(!parent::m_axes[iaxis].configure(a_edges[iaxis])) {
0369         //m_axes.clear();
0370         return false;
0371       }
0372     }
0373 
0374     parent::m_dimension = a_dim;
0375 
0376     base_allocate(); //set m_bin_number.
0377 
0378     return true;
0379   }
0380 
0381   void base_reset() {
0382     // Reset content (different of clear that deallocate all internal things).
0383     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0384       parent::m_bin_entries[ibin] = 0;
0385       parent::m_bin_Sw[ibin] = 0;
0386       parent::m_bin_Sw2[ibin] = 0;
0387       for(dim_t iaxis=0;iaxis<parent::m_dimension;iaxis++) {
0388         parent::m_bin_Sxw[ibin][iaxis] = 0;
0389         parent::m_bin_Sx2w[ibin][iaxis] = 0;
0390       }
0391     }
0392     parent::m_in_range_plane_Sxyw.assign(dim_planes(parent::m_dimension),0);
0393     //profile not done here.
0394     parent::reset_fast_getters();
0395   }
0396 
0397 protected:
0398   void base_allocate() {
0399     dim_t iaxis;
0400     // Add two bins for the [under,out]flow data.
0401     TO n_bin = 1;
0402     for(iaxis=0;iaxis<parent::m_dimension;iaxis++) {
0403       n_bin *= (parent::m_axes[iaxis].bins() + 2);
0404     }
0405 
0406     parent::m_bin_entries.resize(n_bin,0);
0407     parent::m_bin_Sw.resize(n_bin,0);
0408     parent::m_bin_Sw2.resize(n_bin,0);
0409 
0410     std::vector<TC> empty;
0411     empty.resize(parent::m_dimension,0);
0412     parent::m_bin_Sxw.resize(n_bin,empty);
0413     parent::m_bin_Sx2w.resize(n_bin,empty);
0414 
0415     parent::m_bin_number = n_bin; // All bins : [in-range, underflow, outflow] bins.
0416 
0417     parent::m_axes[0].m_offset = 1;
0418     for(iaxis=1;iaxis<parent::m_dimension;iaxis++) {
0419       parent::m_axes[iaxis].m_offset = parent::m_axes[iaxis-1].m_offset * (parent::m_axes[iaxis-1].bins()+2);
0420     }
0421 
0422     parent::m_in_range_plane_Sxyw.resize(dim_planes(parent::m_dimension),0);
0423   }
0424 
0425 public:
0426   // to access data from methods :
0427   const std::vector<TN>& bins_entries() const {return parent::m_bin_entries;}
0428   const std::vector<TW>& bins_sum_w() const {return parent::m_bin_Sw;}
0429   const std::vector<TW>& bins_sum_w2() const {return parent::m_bin_Sw2;}
0430   const std::vector< std::vector<TC> >& bins_sum_xw() const {return parent::m_bin_Sxw;}
0431   const std::vector< std::vector<TC> >& bins_sum_x2w() const {return parent::m_bin_Sx2w;}
0432   const std::vector<TC>& in_range_planes_xyw() const {return parent::m_in_range_plane_Sxyw;}
0433 
0434 public:
0435   const axis_t& get_axis(int a_index) const {return parent::m_axes[a_index];}
0436   offset_t get_bins() const {return parent::m_bin_number;}
0437   const std::string& get_title() const {return parent::m_title;}
0438   dim_t get_dimension() const {return parent::m_dimension;}
0439   bool is_valid() const {return (parent::m_dimension?true:false);}
0440 
0441 public: //annotations :
0442   typedef std::map<std::string,std::string> annotations_t;
0443   const annotations_t& annotations() const {return parent::m_annotations;}
0444   annotations_t annotations() {return parent::m_annotations;}
0445 
0446   void add_annotation(const std::string& a_key,const std::string& a_value) {
0447     parent::m_annotations[a_key] = a_value; //override if a_key already exists.
0448   }
0449   bool annotation(const std::string& a_key,std::string& a_value) const {
0450     annotations_t::const_iterator it = parent::m_annotations.find(a_key);
0451     if(it==parent::m_annotations.end()) {a_value.clear();return false;}
0452     a_value = (*it).second;
0453     return true;
0454   }
0455 
0456   void set_annotations(const annotations_t& a_annotations) {parent::m_annotations = a_annotations;}
0457 
0458   void hprint_annotations(std::ostream& a_out) {
0459     a_out << " * ANNOTATIONS :" << std::endl;
0460     annotations_t::const_iterator it;
0461     for(it=parent::m_annotations.begin();it!=parent::m_annotations.end();++it) {
0462     //out << " * (" << index << ") "
0463       a_out << " *  " << (*it).first << " = " << (*it).second << std::endl;
0464     }
0465   }
0466 
0467 protected:
0468   bool is_compatible(const base_histo& a_histo){
0469     if(parent::m_dimension!=a_histo.m_dimension) return false;
0470     for(dim_t iaxis=0;iaxis<parent::m_dimension;iaxis++) {
0471       if(!parent::m_axes[iaxis].is_compatible(a_histo.m_axes[iaxis])) return false;
0472     }
0473     return true;
0474   }
0475 
0476   void base_add(const base_histo& a_histo){
0477     // The only histogram operation that makes sense.
0478     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0479       parent::m_bin_entries[ibin] += a_histo.m_bin_entries[ibin];
0480       parent::m_bin_Sw[ibin] += a_histo.m_bin_Sw[ibin];
0481       parent::m_bin_Sw2[ibin] += a_histo.m_bin_Sw2[ibin];
0482       for(dim_t iaxis=0;iaxis<parent::m_dimension;iaxis++) {
0483         parent::m_bin_Sxw[ibin][iaxis] += a_histo.m_bin_Sxw[ibin][iaxis];
0484         parent::m_bin_Sx2w[ibin][iaxis] += a_histo.m_bin_Sx2w[ibin][iaxis];
0485       }
0486     }
0487    {size_t nplane = parent::m_in_range_plane_Sxyw.size();
0488     for(size_t iplane=0;iplane<nplane;iplane++)
0489       parent::m_in_range_plane_Sxyw[iplane] += a_histo.m_in_range_plane_Sxyw[iplane];}
0490     parent::update_fast_getters();
0491   }
0492 
0493   void base_subtract(const base_histo& a_histo) {
0494     //ill-defined operation. We keep that because of the "ill-defined past".
0495     // We build a new histo with one entry in each bin.
0496     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0497       parent::m_bin_entries[ibin] = 1;
0498 
0499       parent::m_bin_Sw[ibin] -= a_histo.m_bin_Sw[ibin];
0500       // Yes, it is a += in the below.
0501       parent::m_bin_Sw2[ibin] += a_histo.m_bin_Sw2[ibin];
0502       for(dim_t iaxis=0;iaxis<parent::m_dimension;iaxis++) {
0503         parent::m_bin_Sxw[ibin][iaxis] -= a_histo.m_bin_Sxw[ibin][iaxis];
0504         parent::m_bin_Sx2w[ibin][iaxis] -= a_histo.m_bin_Sx2w[ibin][iaxis];
0505       }
0506     }
0507 
0508  //{for(dim_t iplane=0;iplane<nplane;iplane++) parent::m_in_range_plane_Sxyw[iplane] ??? a_histo.m_in_range_plane_Sxyw[iplane];}
0509 
0510     parent::update_fast_getters();
0511   }
0512 
0513   bool base_multiply(const base_histo& a_histo) {
0514     //ill-defined operation. We keep that because of the "ill-defined past".
0515 
0516     // We build a new histo with one entry in each bin of weight :
0517     //   this.w * a_histo.w
0518     // The current histo is overriden with this new histo.
0519     // The m_bin_Sw2 computation is consistent with FreeHEP and CERN-ROOT.
0520 
0521     if(!is_compatible(a_histo)) return false;
0522 
0523     std::vector<int> is(parent::m_dimension);
0524     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0525       TW swa = parent::m_bin_Sw[ibin];
0526       TW sw2a = parent::m_bin_Sw2[ibin];
0527       TW swb = a_histo.m_bin_Sw[ibin];
0528       TW sw2b = a_histo.m_bin_Sw2[ibin];
0529       TW sw = swa * swb;
0530       parent::m_bin_entries[ibin] = 1;
0531       parent::m_bin_Sw[ibin] = sw;
0532       parent::m_bin_Sw2[ibin] = sw2a * swb * swb + sw2b * swa * swa;
0533       histo::get_indices(parent::m_axes,ibin,is);
0534       for(dim_t iaxis=0;iaxis<parent::m_dimension;iaxis++) {
0535         TC x = parent::m_axes[iaxis].bin_center(is[iaxis]);
0536         parent::m_bin_Sxw[ibin][iaxis] = x * sw;
0537         parent::m_bin_Sx2w[ibin][iaxis] = x * x * sw;
0538       }
0539     }
0540 
0541  //{for(dim_t iplane=0;iplane<nplane;iplane++) parent::m_in_range_plane_Sxyw[iplane] ??? a_histo.m_in_range_plane_Sxyw[iplane];}
0542 
0543     parent::update_fast_getters();
0544     return true;
0545   }
0546 
0547   bool base_divide(const base_histo& a_histo) {
0548     //ill-defined operation. We keep that because of the "ill-defined past".
0549 
0550     // We build a new histo with one entry in each bin of weight :
0551     //   this.w / a_histo.w
0552     // The current histo is overriden with this new histo.
0553     // The m_bin_Sw2 computation is consistent with FreeHEP and ROOT.
0554 
0555     if(!is_compatible(a_histo)) return false;
0556 
0557     std::vector<int> is(parent::m_dimension);
0558     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0559       histo::get_indices(parent::m_axes,ibin,is);
0560       TW swa = parent::m_bin_Sw[ibin];
0561       TW swb = a_histo.m_bin_Sw[ibin];
0562       TW sw2a = parent::m_bin_Sw2[ibin];
0563       TW sw2b = a_histo.m_bin_Sw2[ibin];
0564       if(swb!=0) {
0565         parent::m_bin_entries[ibin] = 1;
0566         TW sw = swa / swb;
0567         parent::m_bin_Sw[ibin] = sw;
0568         TW swb2 = swb * swb;
0569         parent::m_bin_Sw2[ibin] = sw2a / swb2 + sw2b * swa * swa /(swb2*swb2);
0570         for(dim_t iaxis=0;iaxis<parent::m_dimension;iaxis++) {
0571           TC x = parent::m_axes[iaxis].bin_center(is[iaxis]);
0572           parent::m_bin_Sxw[ibin][iaxis] = x * sw;
0573           parent::m_bin_Sx2w[ibin][iaxis] = x * x * sw;
0574         }
0575       } else {
0576         parent::m_bin_entries[ibin] = 0;
0577         parent::m_bin_Sw[ibin] = 0;
0578         parent::m_bin_Sw2[ibin] = 0;
0579         for(dim_t iaxis=0;iaxis<parent::m_dimension;iaxis++) {
0580           parent::m_bin_Sxw[ibin][iaxis] = 0;
0581           parent::m_bin_Sx2w[ibin][iaxis] = 0;
0582         }
0583       }
0584     }
0585 
0586  //{for(dim_t iplane=0;iplane<nplane;iplane++) parent::m_in_range_plane_Sxyw[iplane] ??? a_histo.m_in_range_plane_Sxyw[iplane];}
0587 
0588     parent::update_fast_getters();
0589     return true;
0590   }
0591 
0592   bool base_multiply(TW a_factor) {
0593     if(a_factor<0) return false;
0594     TW factor2 = a_factor * a_factor;
0595     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0596       parent::m_bin_Sw[ibin] *= a_factor;
0597       parent::m_bin_Sw2[ibin] *= factor2;
0598       for(dim_t iaxis=0;iaxis<parent::m_dimension;iaxis++) {
0599         parent::m_bin_Sxw[ibin][iaxis] *= a_factor;
0600         parent::m_bin_Sx2w[ibin][iaxis] *= a_factor;
0601       }
0602     }
0603    {size_t nplane = parent::m_in_range_plane_Sxyw.size();
0604     for(size_t iplane=0;iplane<nplane;iplane++) parent::m_in_range_plane_Sxyw[iplane] *= a_factor;}
0605     parent::update_fast_getters();
0606     return true;
0607   }
0608 
0609   bool get_ith_axis_mean(dim_t a_axis,TC& a_value) const {
0610     a_value = 0;
0611     if(a_axis>=parent::m_dimension) return false;
0612     TW sw = 0;
0613     TC sxw = 0;
0614     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0615       if(!histo::is_out(parent::m_axes,ibin)) {
0616         sw += parent::m_bin_Sw[ibin];
0617         sxw += parent::m_bin_Sxw[ibin][a_axis];
0618       }
0619     }
0620     if(sw==0) return false;
0621     a_value = sxw/sw;
0622     return true;
0623   }
0624 
0625   bool get_ith_axis_rms(dim_t a_axis,TC& a_value) const {
0626     a_value = 0;
0627     if(a_axis>=parent::m_dimension) return false;
0628     TW sw = 0;
0629     TC sxw = 0;
0630     TC sx2w = 0;
0631     for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
0632       if(!histo::is_out(parent::m_axes,ibin)) {
0633         sw += parent::m_bin_Sw[ibin];
0634         sxw += parent::m_bin_Sxw[ibin][a_axis];
0635         sx2w += parent::m_bin_Sx2w[ibin][a_axis];
0636       }
0637     }
0638     if(sw==0) return false;
0639     TC mean = sxw/sw;
0640     a_value = ::sqrt(::fabs((sx2w / sw) - mean * mean));
0641     return true;
0642   }
0643 
0644   TN get_bin_entries(const std::vector<int>& aIs) const {
0645     if(parent::m_bin_number==0) return 0;
0646     TO offset;
0647     if(!histo::get_offset(parent::m_axes,aIs,offset)) return 0;
0648     return parent::m_bin_entries[offset];
0649   }
0650 };
0651 
0652 // predefined annotation keys :
0653 inline const std::string& key_axis_x_title() {
0654   static const std::string s_v("axis_x.title");
0655   return s_v;
0656 }
0657 inline const std::string& key_axis_y_title() {
0658   static const std::string s_v("axis_y.title");
0659   return s_v;
0660 }
0661 inline const std::string& key_axis_z_title() {
0662   static const std::string s_v("axis_z.title");
0663   return s_v;
0664 }
0665 
0666 }}
0667 
0668 #endif