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