MINT2
HistogramBase.cpp
Go to the documentation of this file.
1 #include "Mint/HistogramBase.h"
2 
4 
5 
9  _nBins(nBins),
10  _binContents(nBins+1,0.0),
11  _sumW2 (nBins+1,0.0),
12  _min(-999.9),
13  _max(-999.9),
14  _minDensity(-999.9),
15  _maxDensity(-999.9)
16 {
17  WELCOME_LOG << "Good day from the HistogramBase() Constructor";
18 }
19 
23  _nBins = nBins;
24  _binContents = std::vector<double>(nBins+1,0.0);
25  _sumW2 = std::vector<double>(nBins+1,0.0);
26 }
27 
29  for (unsigned i = 0; i < _binContents.size(); i++){
30  _binContents.at(i) = 0.0;
31  _sumW2 .at(i) = 0.0;
32  }
33 }
34 
35 
36 
38 void HistogramBase::reserveCapacity(int nElements){
39  _binContents.reserve(nElements+1);
40  _sumW2 .reserve(nElements+1);
41 }
42 
43 
46 void HistogramBase::merge( const HistogramBase& other ){
47 
48  double overflowCont = _binContents.at(_nBins);
49  overflowCont += other._binContents.at(other._nBins);
50 
51  double overflowSumW2 = _sumW2.at(_nBins);
52  overflowSumW2 += other._sumW2.at(other._nBins);
53 
54  int capacityNeeded = _nBins + other._nBins + 1;
55 
56  reserveCapacity(capacityNeeded);
57 
58  _binContents.at(_nBins) = other._binContents.at(0);
59  _sumW2 .at(_nBins) = other._sumW2 .at(0);
60 
61  for (int i = 1; i < other._nBins; i++){
62  _binContents.push_back( other._binContents.at(i) );
63  _sumW2 .push_back( other._sumW2 .at(i) );
64  }
65 
66  _binContents.push_back( overflowCont );
67  _sumW2 .push_back( overflowSumW2 );
68 
69  _nBins += other._nBins;
70 
71 }
72 
73 
74 
78 
79  TTree tree("HistogramBase", "HistogramBase");
80 
81  int binNumber = -1;
82  double binContent = 0.0;
83  double sumW2 = 0.0;
84 
85  tree.Branch("binNumber" , &binNumber );
86  tree.Branch("binContent", &binContent);
87  tree.Branch("sumW2" , &sumW2 );
88 
89  for(unsigned int bin = 0; bin < _binContents.size(); bin++ ){
90  binNumber = bin;
91  binContent = _binContents.at(bin);
92  sumW2 = _sumW2 .at(bin);
93  tree.Fill();
94  }
95 
96  tree.Write();
97 
98 }
99 
102 void HistogramBase::saveBase(TString filename){
103 
104  TFile file(filename, "RECREATE");
105 
106  saveBase();
107 
108  file.Write();
109  file.Close();
110 
111 }
112 
115 void HistogramBase::loadBase(TString filename){
116 
117  TFile file(filename, "READ");
118  TTree* tree = (TTree*)file.Get("HistogramBase");
119 
120  int binNumber = -1;
121  double binContent = 0.0;
122  double sumW2 = 0.0;
123 
124  int nEntries = tree->GetEntries();
125 
126  tree->SetBranchAddress("binNumber" , &binNumber );
127  tree->SetBranchAddress("binContent", &binContent);
128  tree->SetBranchAddress("sumW2" , &sumW2 );
129 
130  this->resetBinContents(nEntries - 1);
131 
132 
133  for(int ent = 0; ent < nEntries; ent++){
134  tree->GetEntry(ent);
135 
136  VERBOSE_LOG << "Bin = " << binNumber << " Content = " << binContent << " SumW2 = " << sumW2;
137 
138  _binContents.at((int)binNumber) = binContent;
139  _sumW2 .at((int)binNumber) = sumW2;
140  }
141 
142  file.Close();
143 
144 }
145 
149  GOODBYE_LOG << "Goodbye from the HistogramBase() Constructor";
150 }
151 
155 void HistogramBase::fillBase(int binNum, double weight){
156  binNum = checkBinNumber(binNum);
157  _binContents[binNum] += weight;
158  _sumW2[binNum] += weight*weight;
159 }
160 
163 int HistogramBase::checkBinNumber(int bin) const{
164  if(bin == -1){
165  //This is also a valid way to add to the underflow/overflow bin with no error message
166  return _nBins;
167  }
168  if(bin > _nBins || bin < 0) {
169  ERROR_LOG << "Bin " << bin << " does not exist! Adding to underflow/overflow bin " << _nBins;
170  return _nBins;
171  }
172  return bin;
173 }
174 
177 double HistogramBase::getMin() const{
178  if (_min != -999.9) return _min;
179  MinMaxFinder stats;
180  for (int i = 0; i < _nBins; i++){
181  stats.add( _binContents[i] );
182  }
183  return stats.getMin();
184 }
185 
188 double HistogramBase::getMax() const{
189  if (_max != -999.9) return _max;
190  MinMaxFinder stats;
191  for (int i = 0; i < _nBins; i++){
192  stats.add( _binContents[i] );
193  }
194  return stats.getMax();
195 }
196 
200  if (_minDensity != -999.9) return _minDensity;
201  MinMaxFinder stats;
202  for (int i = 0; i < _nBins; i++){
203  stats.add( getFrequencyDensity(i) );
204  }
205  return stats.getMin();
206 }
207 
211  if (_maxDensity != -999.9) return _maxDensity;
212  MinMaxFinder stats;
213  for (int i = 0; i < _nBins; i++){
214  stats.add( getFrequencyDensity(i) );
215  }
216  return stats.getMax();
217 }
218 
222 
223  if (other._binContents.size() != _binContents.size()){
224  ERROR_LOG << "Trying to divide histograms with different numbers of bins. Doing nothing.";
225  return;
226  }
227 
228  for(unsigned int i = 0; i < _binContents.size(); i++){
229 
230  double binCont1 = _binContents.at(i);
231  double binCont2 = other._binContents.at(i);
232  double var1 = _sumW2.at(i);
233  double var2 = other._sumW2.at(i);
234  double frac1sq = var1/(binCont1*binCont1);
235  double frac2sq = var2/(binCont2*binCont2);
236 
237  double content = binCont1 / binCont2;
238  double var = content*content*(frac1sq + frac2sq);
239 
240  if (binCont2 == 0.0) content = 0.0;
241 
242  _binContents.at(i) = content;
243  _sumW2.at(i) = var;
244 
245  }
246 
247  //reset min and max to default values
248  _min = -999.9;
249  _max = -999.9;
250 }
251 
255 
256  if (other._binContents.size() != _binContents.size()){
257  ERROR_LOG << "Trying to divide histograms with different numbers of bins. Doing nothing.";
258  return;
259  }
260 
261  for(unsigned int i = 0; i < _binContents.size(); i++){
262 
263  double binCont1 = _binContents.at(i);
264  double binCont2 = other._binContents.at(i);
265  double var1 = _sumW2.at(i);
266  double var2 = other._sumW2.at(i);
267  double frac1sq = var1/(binCont1*binCont1);
268  double frac2sq = var2/(binCont2*binCont2);
269 
270  double content = binCont1 * binCont2;
271  double var = content*content*(frac1sq + frac2sq);
272 
273  _binContents.at(i) = content;
274  _sumW2.at(i) = var;
275 
276  }
277 
278  //reset min and max to default values
279  _min = -999.9;
280  _max = -999.9;
281 
282 }
283 
287 
288  if (other._binContents.size() != _binContents.size()){
289  ERROR_LOG << "Trying to divide histograms with different numbers of bins. Doing nothing.";
290  return;
291  }
292 
293  for(unsigned int i = 0; i < _binContents.size(); i++){
294 
295  double binCont1 = _binContents.at(i);
296  double binCont2 = other._binContents.at(i);
297  double var1 = _sumW2.at(i);
298  double var2 = other._sumW2.at(i);
299 
300  double content = binCont1 + binCont2;
301  double var = var1 + var2;
302 
303  _binContents.at(i) = content;
304  _sumW2.at(i) = var;
305 
306  }
307 
308  //reset min and max to default values
309  _min = -999.9;
310  _max = -999.9;
311 
312 }
313 
317 
318  if (other._binContents.size() != _binContents.size()){
319  ERROR_LOG << "Trying to divide histograms with different numbers of bins. Doing nothing.";
320  return;
321  }
322 
323  for(unsigned int i = 0; i < _binContents.size(); i++){
324 
325  double binCont1 = _binContents.at(i);
326  double binCont2 = other._binContents.at(i);
327  double var1 = _sumW2.at(i);
328  double var2 = other._sumW2.at(i);
329 
330  double content = binCont1 - binCont2;
331  double var = var1 + var2;
332 
333  _binContents.at(i) = content;
334  _sumW2.at(i) = var;
335 
336  }
337 
338  //reset min and max to default values
339  _min = -999.9;
340  _max = -999.9;
341 
342 }
343 
347 
348  if (other._binContents.size() != _binContents.size()){
349  ERROR_LOG << "Trying to divide histograms with different numbers of bins. Doing nothing.";
350  return;
351  }
352 
353  for( int i = 0; i < getNBins(); i++){
354 
355  double binCont1 = _binContents.at(i);
356  double binCont2 = other._binContents.at(i);
357  double var1 = _sumW2.at(i);
358  double var2 = other._sumW2.at(i);
359 
360  double content = binCont1 - binCont2;
361  double var = var1 + var2;
362 
363  _binContents.at(i) = content/sqrt(var);
364  _sumW2.at(i) = 0.0;
365 
366  }
367 
368  //reset min and max to default values
369  _min = -999.9;
370  _max = -999.9;
371 }
372 
373 
376 void HistogramBase::pulls(const HistogramBase& other1, const HistogramBase& other2){
377 
378  if (other1._binContents.size() != _binContents.size() || other2._binContents.size() != _binContents.size()){
379  ERROR_LOG << "Trying to divide histograms with different numbers of bins. Doing nothing.";
380  return;
381  }
382 
383  for( int i = 0; i < getNBins(); i++){
384 
385  double binCont1 = other1._binContents.at(i);
386  double binCont2 = other2._binContents.at(i);
387  double var1 = other1._sumW2.at(i);
388  double var2 = other2._sumW2.at(i);
389 
390  double content = binCont1 - binCont2;
391  double var = var1 + var2;
392 
393  _binContents.at(i) = content/sqrt(var);
394  _sumW2.at(i) = 0.0;
395 
396  }
397 
398  //reset min and max to default values
399  _min = -999.9;
400  _max = -999.9;
401 }
402 
403 
405 
406  if (other._binContents.size() != _binContents.size()){
407  ERROR_LOG << "Trying to divide histograms with different numbers of bins. Doing nothing.";
408  return;
409  }
410 
411  for( int i = 0; i < getNBins(); i++){
412 
413  double binCont1 = _binContents.at(i);
414  double binCont2 = other._binContents.at(i);
415  double var1 = _sumW2.at(i);
416  double var2 = other._sumW2.at(i);
417 
418  double content = (binCont1 - binCont2)/(binCont1 + binCont2);
419 
420  double dzdx = (2.0*binCont2)/((binCont1 + binCont2)*(binCont1 + binCont2));
421  double dzdy = (2.0*binCont1)/((binCont1 + binCont2)*(binCont1 + binCont2));
422  double varsq = dzdx*dzdx*var1*var1 + dzdy*dzdy*var2*var2;
423 
424  _binContents.at(i) = content;
425  _sumW2.at(i) = varsq;
426 
427  }
428 
429  //reset min and max to default values
430  _min = -999.9;
431  _max = -999.9;
432 
433 }
434 
435 void HistogramBase::asymmetry(const HistogramBase& other1, const HistogramBase& other2){
436 
437  if (other1._binContents.size() != _binContents.size() || other2._binContents.size() != _binContents.size()){
438  ERROR_LOG << "Trying to divide histograms with different numbers of bins. Doing nothing.";
439  return;
440  }
441 
442  for( int i = 0; i < getNBins(); i++){
443 
444  double binCont1 = other1._binContents.at(i);
445  double binCont2 = other2._binContents.at(i);
446  double var1 = other1._sumW2.at(i);
447  double var2 = other2._sumW2.at(i);
448 
449  double content = (binCont1 - binCont2)/(binCont1 + binCont2);
450 
451  double dzdx = (2.0*binCont2)/((binCont1 + binCont2)*(binCont1 + binCont2));
452  double dzdy = (2.0*binCont1)/((binCont1 + binCont2)*(binCont1 + binCont2));
453  double varsq = dzdx*dzdx*var1*var1 + dzdy*dzdy*var2*var2;
454 
455  _binContents.at(i) = content;
456  _sumW2.at(i) = varsq;
457 
458  }
459 
460  //reset min and max to default values
461  _min = -999.9;
462  _max = -999.9;
463 
464 }
465 
466 
467 
473 
474  TRandom3 random(seed);
475 
476  for( int i = 0; i < getNBins(); i++){
477 
478  double mean = _binContents.at(i);
479  double sigma = sqrt(_sumW2.at(i));
480 
481  double newContent = random.Gaus(mean, sigma);
482  if (newContent < 0.0) newContent = 0.0;
483  _binContents.at(i) = newContent;
484  }
485 
486 }
487 
492 double HistogramBase::pvalue(const HistogramBase& other, int ndof) const{
493 
494  if (ndof < 0.0) ndof = getNBins();
495  double chi2 = this->chi2(other);
496 
497  return TMath::Prob(chi2, ndof);
498 
499 }
500 
504 double HistogramBase::chi2sig(const HistogramBase& other, int ndof) const{
505 
506  double pval = pvalue(other, ndof);
507  double sigma = TMath::NormQuantile( pval/2.0 );
508  return fabs(sigma);
509 
510 }
511 
512 
515 double HistogramBase::chi2(const HistogramBase& other) const{
516 
517  double chi2 = 0.0;
518 
519  for( int i = 0; i < getNBins(); i++){
520 
521  double binCont1 = _binContents.at(i);
522  double binCont2 = other._binContents.at(i);
523  double var1 = _sumW2.at(i);
524  double var2 = other._sumW2.at(i);
525 
526  double content = binCont1 - binCont2;
527  double var = var1 + var2;
528 
529  double thisTerm = (content * content) / var;
530 
531  chi2 += thisTerm;
532 
533  }
534 
535  return chi2;
536 
537 }
538 
542 void HistogramBase::drawPullHistogram(const HistogramBase& other, TString name, int nBins, double pmLimits) const{
543 
544  TH1D pulls ("pulls", "pulls", nBins, -pmLimits, pmLimits);
545  pulls.GetXaxis()->SetTitle("pull");
546  pulls.GetYaxis()->SetTitle("frequency");
547  for( int i = 0; i < getNBins(); i++){
548 
549  double binCont1 = _binContents.at(i);
550  double binCont2 = other._binContents.at(i);
551  double var1 = _sumW2.at(i);
552  double var2 = other._sumW2.at(i);
553 
554  double content = binCont1 - binCont2;
555  double var = var1 + var2;
556 
557  double pull = (content) / sqrt(var);
558  pulls.Fill(pull);
559 
560  }
561 
562  RootPlotter1D plotter(&pulls);
563  plotter.plot(name);
564 
565 }
566 
569 double HistogramBase::integral() const{
570  double integral = 0.0;
571  for(int i = 0; i < getNBins() ; i++){
572  integral += _binContents.at(i);
573  }
574  return integral;
575 }
576 
580  double var = 0.0;
581  for(int i = 0; i < getNBins() ; i++){
582  var += _sumW2.at(i);
583  }
584  return sqrt(var);
585 }
586 
589 void HistogramBase::normalise(double area){
590 
591  double divisor = integral()/area;
592  double divisor2 = divisor*divisor;
593 
594  for( int i = 0; i < getNBins(); i++){
595  _binContents.at(i) = _binContents.at(i)/divisor;
596  _sumW2 .at(i) = _sumW2 .at(i)/divisor2;
597  }
598 
599 }
600 
603 void HistogramBase::setBinContent(int bin, double val){
604  bin = checkBinNumber(bin);
605  _binContents[bin] = val;
606 }
607 
610 void HistogramBase::setBinError (int bin, double val){
611  bin = checkBinNumber(bin);
612  _sumW2[bin] = val*val;
613 }
614 
617 double HistogramBase::getBinContent(int bin) const{
618  bin = checkBinNumber(bin);
619  return _binContents[bin];
620 }
621 
624 double HistogramBase::getBinError (int bin) const{
625  bin = checkBinNumber(bin);
626  return sqrt(_sumW2[bin]);
627 }
628 
632 double HistogramBase::getBinVolume(int bin) const{
633  bin = checkBinNumber(bin);
634  return 1.0;
635 }
636 
640 
641  return getBinContent(bin)/getBinVolume(bin);
642 
643 }
644 
648 
649  for(int i = 0; i < _nBins; i++){
650  double binVolume = this->getBinVolume(i);
651  _binContents[i] = _binContents[i] / binVolume;
652  _sumW2[i] = _sumW2[i] / (binVolume*binVolume);
653  }
654 
655 }
656 
660 
661  for(int i = 0; i < _nBins; i++){
662  INFO_LOG << "Bin Content " << i << ": " << _binContents[i] << " SumW2: " << _sumW2[i];
663  }
664  INFO_LOG << "Overflow: " << _binContents[_nBins];
665 
666 }
667 
void loadBase(TString filename)
double chi2(const HistogramBase &other) const
double getMaxDensity() const
double getBinError(int bin) const
int getNBins() const
Definition: HistogramBase.h:63
#define INFO_LOG
virtual void merge(const HistogramBase &other)
std::vector< double > _binContents
Definition: HistogramBase.h:35
void asymmetry(const HistogramBase &other)
virtual ~HistogramBase()
void setBinError(int bin, double val)
std::vector< double > _sumW2
Definition: HistogramBase.h:36
#define ERROR_LOG
void add(const double &x, const double &weight=1.0)
virtual double getBinVolume(int bin) const
HistogramBase(int nBins)
const double & getMin() const
double getBinContent(int bin) const
void setBinContent(int bin, double val)
double getMin() const
#define VERBOSE_LOG
void fillBase(int binNum, double weight)
void makeFrequencyDensity()
double chi2sig(const HistogramBase &other, int ndof=-1) const
double getFrequencyDensity(int bin) const
double getMax() const
void resetBinContents(int nBins)
void multiply(const HistogramBase &other)
virtual void plot(TString plotDirectory, TString plotOptions="", TPad *pad=0, double scaleFactor=1.0)
void drawPullHistogram(const HistogramBase &other, TString name, int nBins=50, double pmLimits=3.5) const
#define GOODBYE_LOG
void reserveCapacity(int nElements)
void minus(const HistogramBase &other)
void randomiseWithinErrors(int seed)
double _minDensity
Definition: HistogramBase.h:40
void divide(const HistogramBase &other)
#define WELCOME_LOG
int checkBinNumber(int bin) const
void normalise(double area=1.0)
const double & getMax() const
void pulls(const HistogramBase &other)
double pvalue(const HistogramBase &other, int ndof=-1) const
double integral() const
double _maxDensity
Definition: HistogramBase.h:41
double integralError() const
double getMinDensity() const
void add(const HistogramBase &other)