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