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