HighLAND
HistoStack.cxx
1 #include "HistoStack.hxx"
2 #include <cmath>
3 #include "TCanvas.h"
4 
5 //********************************************************
6 HistoStack::HistoStack(const std::string& title, const std::string& titleX, const std::string& titleY) {
7 //*******************************************************
8 
9  _title = title;
10  _titleX = titleX;
11  _titleY = titleY;
12 
13  _hall1D = NULL;
14  _hall2D = NULL;
15 
16  _hall1D_stat = NULL;
17  _hall1D_syst = NULL;
18 
19  _is1D = false;
20  _is2D = false;
21 
22  _stack = NULL;
23  _hall1D_draw = NULL;
24 
25  // _h1 = _h2 = _h1w = NULL;
26 
27  _systHistosGroups.clear();
28 
29  _currentSystGroup ="default";
30 
31 }
32 
33 //********************************************************
35 //*******************************************************
36 
37  if (_hall1D) delete _hall1D;
38  if (_hall2D) delete _hall2D;
39 
40  if (_hall1D_syst) delete _hall1D_syst;
41  if (_hall1D_stat) delete _hall1D_stat;
42 
43  std::map<std::string, TH1_h*>::iterator itm1;
44  std::map<std::string, TH2_h*>::iterator itm2;
45  for (itm2 = _h1.begin(); itm2 != _h1.end(); itm2++)
46  if (itm2->second) delete itm2->second;
47  _h1.clear();
48 
49  for (itm2 = _h2.begin(); itm2 != _h2.end(); itm2++)
50  if (itm2->second) delete itm2->second;
51  _h2.clear();
52 
53  for (itm2 = _h1w.begin(); itm2 != _h1w.end(); itm2++)
54  if (itm2->second) delete itm2->second;
55  _h1w.clear();
56 
57  _systHistosGroups.clear();
58 
59  std::vector<TH1_h*>::iterator it1;
60  for (it1 = _histos1D.begin(); it1 != _histos1D.end(); it1++) delete *it1;
61  _histos1D.clear();
62 
63  std::vector<TH2_h*>::iterator it2;
64  for (it2 = _histos2D.begin(); it2 != _histos2D.end(); it2++) delete *it2;
65  _histos2D.clear();
66 
67  // delete also the histograms created for drawing
69 }
70 
71 
72 //********************************************************
74 //*******************************************************
75 
76  if (_hall1D_draw) delete _hall1D_draw;
77 
78  if (_histos1D_draw.size()>0){
79  for (std::vector<TH1_h*>::iterator it1 = _histos1D_draw.begin(); it1 != _histos1D_draw.end(); it1++)
80  delete *it1;
81  _histos1D_draw.clear();
82  }
83 
84 }
85 
86 //********************************************************
87 TH1_h* HistoStack::GetHisto1D(const std::string& title) {
88 //*******************************************************
89 
90  if (_histos1D.size() > 0) {
91  std::vector<TH1_h*>::reverse_iterator rit1;
92  for (rit1 = _histos1D.rbegin(); rit1 != _histos1D.rend(); rit1++) {
93  if (strcmp((*rit1)->GetTitle(), title.c_str())==0)
94  return *rit1;
95  }
96  }
97 
98  return NULL;
99 }
100 
101 //********************************************************
102 TH1_h* HistoStack::GetHisto1D(Int_t index) {
103 //*******************************************************
104 
105  if (index >= 0 && (UInt_t)index < _histos1D.size()) {
106  return _histos1D[index];
107  }
108 
109  return NULL;
110 }
111 
112 
113 //********************************************************
114 TH2_h* HistoStack::GetHisto2D(const std::string& title) {
115 //*******************************************************
116 
117  if (_histos2D.size() > 0) {
118  std::vector<TH2_h*>::reverse_iterator rit1;
119  for (rit1 = _histos2D.rbegin(); rit1 != _histos2D.rend(); rit1++) {
120  if (strcmp((*rit1)->GetTitle(), title.c_str())==0)
121  return *rit1;
122  }
123  }
124  return NULL;
125 }
126 
127 //********************************************************
128 TH2_h* HistoStack::GetHisto2D(Int_t index) {
129 //*******************************************************
130 
131  if (index >=0 && (UInt_t)index < _histos2D.size()) {
132  return _histos2D[index];
133  }
134 
135  return NULL;
136 }
137 
138 
139 //********************************************************
140 void HistoStack::Draw(const std::string& root_opt, const std::string& opt) {
141 //*******************************************************
142 
143  Draw(1,1,1,0,root_opt,opt,"",0);
144 
145 }
146 
147 //********************************************************
148 void HistoStack::Draw(int lc, int lw, int fc, int fs, const std::string& root_opt, const std::string& opt,const std::string& leg_opt,int mode) {
149 //*******************************************************
150 
151  (void)leg_opt;
152  (void)mode;
153 
154  // Delete all histos used for drawing the stack, just in case this stack was drawn before
155  ResetDrawHistos();
156 
157  if (_is1D) {
158  bool makeTotal = (!_hall1D);
159 
160  std::vector<TH1_h*>::reverse_iterator rit1;
161  int i = 0;
162  for (rit1 = _histos1D.rbegin(); rit1 != _histos1D.rend(); rit1++, i++) {
163  TH1_h* ht = *rit1;
164 
165  if (makeTotal) {
166  if (i == 0) {
167  _hall1D = new TH1_h(*ht);
168  _hall1D->SetName((std::string(ht->GetName()) + "_cum").c_str());
169  _hall1D->SetTitle(ht->GetTitle());
170  } else {
171  _hall1D->Add(_hall1D, ht);
172  }
173  }
174  if (i == 0) {
175  if (_stack) delete _stack;
176  _stack = new THStack((std::string(ht->GetName()) + "_stack").c_str(), _title.c_str());
177  }
178  }
179 
180  // Copy the histogram before normalizing
181  _hall1D_draw = new TH1_h(*_hall1D);
182  Double_t min_width;
183  drawUtils::NormalizeVariableBinning(_hall1D_draw,2,opt, min_width);
184 
185  for (rit1 = _histos1D.rbegin(); rit1 != _histos1D.rend(); rit1++) {
186  TH1_h* ht = *rit1;
187  // Clone the histograms before normalizing
188  TH1_h* htp = new TH1_h(*ht);
189  _histos1D_draw.push_back(htp);
190  drawUtils::NormalizeVariableBinning(htp,2,opt+" USEMINWIDTH",min_width);
191  // Add the normalized histo to the stack
192  _stack->Add(htp);
193  }
194 
195 
196  // Set the maximum and minimum Y
197  // double maxy = _hall1D_draw->GetBinContent(_hall1D_draw->GetMaximumBin()) * 1.1;
198  // if (_stack && opt.find("ETOT")) {
199  // maxy += _hall1D_draw->GetBinError(_hall1D_draw->GetMaximumBin()) * 1.1;
200  // }
201 
202  // if (fabs(usermaxY) > 1e-6 && usermaxY > userminY) {
203  // maxy = usermaxY;
204  // }
205  // double miny = userminY;
206 
207  // If the stack is pressent (colore drawing) just draw it
208  if (_stack){
209  if (root_opt.find("same") == std::string::npos) {
210  _stack->Draw(("HIST"+root_opt).c_str());
211  _stack->GetXaxis()->SetTitle(_titleX.c_str());
212  _stack->GetYaxis()->SetTitle(_titleY.c_str());
213  _stack->Draw(("HIST"+root_opt).c_str());
214  } else {
215  _stack->Draw("HIST same");
216  }
217  }
218 
219  // This is just to draw the stats box before doing the variable bin normalization
220  _hall1D->GetXaxis()->SetTitle(_titleX.c_str());
221  _hall1D->GetYaxis()->SetTitle(_titleY.c_str());
222  _hall1D->SetTitle(_title.c_str());
223 
224 
225  if (_stack)
226  _hall1D->Draw((root_opt+"sames AXIS").c_str());
227  else
228  _hall1D->Draw((root_opt+"AXIS").c_str());
229 
230 
231  // Style for the total histo in the case it has to be drawn
232  _hall1D_draw->SetLineColor(lc);
233  _hall1D_draw->SetMarkerColor(lc);
234  _hall1D_draw->SetLineWidth(lw);
235  _hall1D_draw->SetFillColor(fc);
236  _hall1D_draw->SetFillStyle(fs);
237 
238  // Draw error bars for the total stack when requested
239  if (_stack && drawUtils::CheckOption(opt, "ETOT")) {
240  _hall1D_draw->Draw("same e2");
241  }
242  // Draw the total when there is no stack
243  if (!_stack){
244  _hall1D_draw->SetMarkerStyle(20);
245  _hall1D_draw->SetMarkerSize(1);
246  _hall1D_draw->Draw((root_opt+"same").c_str());
247 
248  if (_hall1D_stat){
249  _hall1D_stat->SetLineColor(4);
250  _hall1D_stat->SetFillColor(4);
251  _hall1D_stat->Draw((root_opt+"same").c_str());
252  }
253  }
254 
255  } else if (_is2D) {
256  bool makeTotal = (!_hall2D);
257 
258  std::vector<TH2_h*>::reverse_iterator rit1;
259  int i = 0;
260  for (rit1 = _histos2D.rbegin(); rit1 != _histos2D.rend(); rit1++, i++) {
261  TH2_h* ht = *rit1;
262 
263  if (makeTotal) {
264  if (i == 0) {
265  _hall2D = new TH2_h(*ht);
266  _hall2D->SetName((std::string(ht->GetName()) + "_cum").c_str());
267  _hall2D->SetTitle(ht->GetTitle());
268  } else {
269  _hall2D->Add(_hall2D, ht);
270  }
271  }
272  if (i == 0) {
273  if (_stack) delete _stack;
274  _stack = new THStack((std::string(ht->GetName()) + "_stack").c_str(), _title.c_str());
275  }
276  _stack->Add(ht);
277 
278  }
279 
280 
281  // Style for the total histo in the case it has to be drawn
282  _hall2D->SetLineColor(lc);
283  _hall2D->SetMarkerColor(lc);
284  _hall2D->SetLineWidth(lw);
285  _hall2D->SetFillColor(fc);
286  _hall2D->SetFillStyle(fs);
287 
288  if (_stack){
289  if (root_opt.find("same") == std::string::npos) {
290  _stack->Draw(("HIST "+root_opt).c_str());
291  _stack->GetXaxis()->SetTitle(_titleX.c_str());
292  _stack->GetYaxis()->SetTitle(_titleY.c_str());
293  _stack->Draw(("HIST "+root_opt).c_str());
294  } else {
295  _stack->Draw("HIST same");
296  }
297  }
298  else{
299  _hall2D->Draw(root_opt.c_str());
300  }
301  }
302 
303 }
304 
305 //********************************************************
306 void HistoStack::FillLegend(TLegend* leg){
307 //*******************************************************
308 
309  // Fill the legend using the titles
310 
311  if (_histos1D.size() > 0) {
312  std::vector<TH1_h*>::iterator it1;
313  for (it1 = _histos1D.begin(); it1 != _histos1D.end(); it1++) {
314  TH1_h* ht = *it1;
315  drawUtils::AddLegendEntry( leg, ht, ht->GetTitle(),"f");
316  }
317  } else if (_histos2D.size() > 0) {
318  std::vector<TH2_h*>::iterator it1;
319  for (it1 = _histos2D.begin(); it1 != _histos2D.end(); it1++) {
320  TH2_h* ht = *it1;
321  drawUtils::AddLegendEntry( leg, ht, ht->GetTitle(),"f");
322  }
323  }
324 }
325 
326 
327 //********************************************************
328 void HistoStack::AddTotal(TH1_h* h1, TH1_h* hsyst) {
329 //*******************************************************
330 
331  _is1D = true;
332 
333  // The name of the total histogram is the title of the stack
334  // h1->SetName(_title.c_str());
335 
336  if (_currentSystGroup == "default"){
337  if (_hall1D){
338  _hall1D->Add(h1);
339  if (hsyst){
340  _hall1D_stat->Add(h1);
341  _hall1D_syst->Add(h1);
342  }
343  }
344  else{
345  _hall1D = new TH1_h(*h1);
346  if (hsyst){
347  _hall1D_syst = new TH1_h(*h1);
348  _hall1D_stat = new TH1_h(*h1);
349  }
350  }
351  }
352 
353  //When a realitive systematic histo is provided
354  if (hsyst){
355  for (int i=0;i<hsyst->GetNbinsX();i++){
356  // Compute the total systematic
357  double err_syst = hsyst->GetBinError(i+1)*_hall1D_stat->GetBinContent(i+1);
358  _hall1D_syst->SetBinError(i+1,err_syst);
359 
360  // Add stat and syst errors in quadrature
361  double err_total = sqrt(pow(_hall1D_stat->GetBinError(i+1),2)+pow(_hall1D_syst->GetBinError(i+1),2));
362  _hall1D->SetBinError(i+1,err_total);
363  }
364  }
365  /*
366  else{
367  for (int i=0;i<_hall1D_syst->GetNbinsX();i++){
368  _hall1D_syst->SetBinError(i+1,0);
369  }
370  }
371  */
372 }
373 
374 //********************************************************
375 void HistoStack::AddTotal(TH2_h* h2) {
376 //*******************************************************
377 
378  _is2D = true;
379 
380  // The name of the total histogram is the title of the stack
381  // h2->SetName(_title.c_str());
382 
383  if (_hall2D)
384  _hall2D->Add(h2);
385  else
386  _hall2D = new TH2_h(*h2);
387 }
388 
389 
390 //********************************************************
391 void HistoStack::AddSystHistos(TH2_h* h1, TH2_h* h2, TH2_h* h1w){
392 //*******************************************************
393 
394  std::string group = _currentSystGroup;
395 
396  if (group==""){
397  std::cout << "Error in HistoStack::AddSystHistos !!! Current Systematics Group not specified !!!" << std::endl;
398  return;
399  }
400 
401  if (_h1.find(group)!=_h1.end()){
402  _h1[group]->Add(h1);
403  _h1w[group]->Add(h1w);
404  _h2[group]->Add(h2);
405  return;
406  }
407 
408  AddSystHistosGroup(group);
409 
410  _h1[group] = new TH2_h(*h1);
411  _h1[group]->SetName("h1p");
412 
413  _h1w[group] = new TH2_h(*h1w);
414  _h1w[group]->SetName("h1wp");
415 
416  _h2[group] = new TH2_h(*h2);
417  _h2[group]->SetName("h2p");
418 }
419 
420 //********************************************************
421 void HistoStack::GetSystHistos(const std::string& group, TH2_h*& h1, TH2_h*& h2,TH2_h*& h1w){
422 //*******************************************************
423 
424  h1 = _h1[group];
425  h1w = _h1w[group];
426  h2 = _h2[group];
427 
428 }
429 
430 //********************************************************
431 void HistoStack::Add(TH1_h* h1, int lc, int lw, int fc, int fs,const std::string& leg) {
432 //*******************************************************
433 
434  if (_is2D) return;
435  _is1D = true;
436 
437  // Check whether a histo with the same title already exists
438  TH1_h* h1p = GetHisto1D(leg);
439  if (h1p){
440  // if it exists we need to add the new one to the existing one
441  h1p->Add(h1);
442  return;
443  }
444 
445  //---- We get here when this title is new ------
446 
447  TH1_h* h1pp = new TH1_h(*h1);
448 
449  // set the atributes for this histo in the stacked plot
450  h1pp->SetFillColor(fc);
451  h1pp->SetLineColor(lc);
452  h1pp->SetLineWidth(lw);
453  h1pp->SetFillStyle(fs);
454 
455  if (fs == 0)
456  h1pp->SetMarkerStyle(21);
457 
458  // Set the title
459  if (leg!="")
460  h1pp->SetTitle(leg.c_str());
461 
462  // add the histo to the vector
463  _histos1D.push_back(h1pp);
464 }
465 
466 //********************************************************
467 void HistoStack::Add(TH2_h* h2, int fc, int lc, const std::string& leg) {
468 //*******************************************************
469 
470  if (_is1D) return;
471  _is2D = true;
472 
473  // Check whether a histo with the same title already exists
474  TH2_h* h2p = GetHisto2D(leg);
475  if (h2p){
476  // if it exists we need to add the new one to the existing one
477  h2p->Add(h2);
478  return;
479  }
480 
481  //---- We get here when this title is new ------
482 
483  TH2_h* h2pp = new TH2_h(*h2);
484 
485  // set the atributes for this histo in the stacked plot
486  h2pp->SetFillColor(fc);
487  h2pp->SetLineColor(lc);
488  h2pp->SetMarkerColor(lc);
489 
490  // set the title
491  if (leg!="")
492  h2pp->SetTitle(leg.c_str());
493 
494  // add the histo to the vector
495  _histos2D.push_back(h2pp);
496 }
497 
498 //********************************************************
499 void HistoStack::NormalizeByArea(const std::string& uopt, double area){
500 //*******************************************************
501 
502  if (!drawUtils::CheckOption(uopt, "AREA") || drawUtils::CheckInternalOption(uopt, "NOAREA")) return;
503 
504  if (_hall1D){
505  double integral = _hall1D->GetSumOfWeights();
506  if(integral > 0.){
507  if (drawUtils::CheckOption(uopt, "AREA100")) area = 100;
508  else if (drawUtils::CheckOption(uopt, "AREA1")) area = 1.;
509  else if (area==1) return;
510 
511  _hall1D->Sumw2();
512  _hall1D->Scale(area/integral);
513 
514  if (_hall1D_syst){
515  _hall1D_syst->Sumw2();
516  _hall1D_syst->Scale(area/integral);
517  }
518 
519  if (_hall1D_stat){
520  _hall1D_stat->Sumw2();
521  _hall1D_stat->Scale(area/integral);
522  }
523 
524  if (_histos1D.size() > 0) {
525  std::vector<TH1_h*>::iterator it1;
526  for (it1 = _histos1D.begin(); it1 != _histos1D.end(); it1++) {
527  TH1_h* ht = *it1;
528  ht->Scale(area/integral);
529  }
530  }
531  }
532  }
533 
534 }
535 
536 
537 //*********************************************************
538 double HistoStack::GetMaximum(const std::string& opt){
539 //*********************************************************
540 
541  // we must normalizeto the minimum width bin before getting the maximum
542  if (!_hall1D_draw){
543  _hall1D_draw = new TH1_h(*_hall1D);
544  Double_t min_width;
546  }
547 
548  return _hall1D_draw->GetBinContent(_hall1D_draw->GetMaximumBin());
549 }
550 
551 //*********************************************************
552 double HistoStack::GetMaximumWithError(const std::string& opt){
553 //*********************************************************
554 
555  // Note: TH1_h::GetBinErrorUp() was used in this function in stead of TH1_h::GetBinError(). That
556  // function is not available on ROOT 5.30, which is the default for production 5. Thus this
557  // function cannot be used here, as we need production 5 compatibility!
558 
559  // we must normalizeto the minimum width bin before getting the maximum
560  if (!_hall1D_draw){
561  _hall1D_draw = new TH1_h(*_hall1D);
562  Double_t min_width;
564  }
565 
566  return _hall1D_draw->GetBinContent(_hall1D_draw->GetMaximumBin())+_hall1D_draw->GetBinError(_hall1D_draw->GetMaximumBin());
567 }
568 
569 
570 //*********************************************************
571 void HistoStack::SetMaximum(double max){
572 //*********************************************************
573 
574  _hall1D->SetMaximum(max);
575  if (_hall1D_draw) _hall1D_draw->SetMaximum(max);
576  if (_stack) _stack->SetMaximum(max);
577 }
578 
579 
580 //*********************************************************
581 void HistoStack::SetMinimum(double min){
582 //*********************************************************
583 
584  _hall1D->SetMinimum(min);
585  if (_hall1D_draw) _hall1D_draw->SetMinimum(min);
586  if (_stack) _stack->SetMinimum(min);
587 }
588 
589 //*********************************************************
590 void HistoStack::Print() const{
591 //*********************************************************
592 
593  std::cout << "---------- Dumping HistoStack -----------" << std::endl;
594 
595  std::vector<TH1_h*>::const_iterator rit1;
596  for (rit1 = _histos1D.begin(); rit1 != _histos1D.end(); rit1++) {
597  std::cout << " - " << (*rit1)->GetTitle() << " " << (*rit1)->GetEntries() << std::endl;
598  }
599 }
void Draw(int lc, int lw, int fc, int fs, const std::string &root_opt="", const std::string &opt="", const std::string &leg_opt="", int mode=0)
Definition: HistoStack.cxx:148
bool _is2D
is it 2D ?
Definition: HistoStack.hxx:182
bool _is1D
is it 1D ?
Definition: HistoStack.hxx:179
TH2_h * GetHisto2D(const std::string &title)
Returns one of the histos in the 2D stack. The title is used for comparison.
Definition: HistoStack.cxx:114
void ResetDrawHistos()
delete all temporary histos used for drawing the stak (with variable binning normalization) ...
Definition: HistoStack.cxx:73
void AddTotal(TH1_h *h1, TH1_h *hsyst=NULL)
Sets the total 1D histo if it does not exists or adds to the previous one when it exists...
Definition: HistoStack.cxx:328
TH1_h * GetHisto1D(const std::string &title)
Returns one of the histos in the 1D stack. The title is used for comparison.
Definition: HistoStack.cxx:87
void AddLegendEntry(TLegend *leg, TObject *ht, const std::string &type, const std::string &opt)
Add an entry to the Legend and resize it.
THStack * _stack
The root stack.
Definition: HistoStack.hxx:150
TH1_h * _hall1D_stat
The "total" 1D histogram with only stat errors.
Definition: HistoStack.hxx:157
void NormalizeVariableBinning(TH1 *h, int mode, const std::string &opt, Double_t &minwidth)
Normalize bin contents by bin width. return the with of the bin with minimum width.
TH1_h * _hall1D
Definition: HistoStack.hxx:154
void FillLegend(TLegend *leg)
Fill the legend with info in the HistoStack.
Definition: HistoStack.cxx:306
void AddSystHistosGroup(const std::string &group)
Add a new group of systemtic histos.
Definition: HistoStack.hxx:88
std::string _title
The title of the plot.
Definition: HistoStack.hxx:170
double GetMaximum(const std::string &opt="")
Get the maximum for the HistoStack.
Definition: HistoStack.cxx:538
void SetMinimum(double min)
Set the minimum for the HistoStack.
Definition: HistoStack.cxx:581
virtual ~HistoStack()
Definition: HistoStack.cxx:34
void NormalizeByArea(const std::string &uopt, double area=1)
normalize all histos in the stack by area
Definition: HistoStack.cxx:499
std::vector< std::string > _systHistosGroups
Histos for updating systematics when using several files.
Definition: HistoStack.hxx:185
HistoStack(const std::string &title, const std::string &titleX, const std::string &titleY)
Definition: HistoStack.cxx:6
std::vector< TH1_h * > _histos1D_draw
The TH1_hs that were added to the stack. Temporary histos used for drawing the stack (with variable b...
Definition: HistoStack.hxx:144
void SetMaximum(double max)
Set the maximum for the HistoStack.
Definition: HistoStack.cxx:571
TH1_h * _hall1D_syst
The "total" 1D histogram with only systematic errors.
Definition: HistoStack.hxx:160
void Add(TH1_h *h1, int lc, int lw, int fc, int fs, const std::string &leg)
Add a new 1D histogram to the stack, with fill colour "fc", line colour "lc".
Definition: HistoStack.cxx:431
void Print() const
Dump the stack contents.
Definition: HistoStack.cxx:590
TH1_h * _hall1D_draw
temporary histo used for drawing the total (with variable binning normalization)
Definition: HistoStack.hxx:163
std::vector< TH2_h * > _histos2D
The TH2_hs that were added to the stack.
Definition: HistoStack.hxx:147
void AddSystHistos(TH2_h *h1, TH2_h *h2, TH2_h *h1w)
Add histos for updating systematics when using several files.
Definition: HistoStack.cxx:391
double GetMaximumWithError(const std::string &opt="")
Get the maximum for the HistoStack taking into account the upper error.
Definition: HistoStack.cxx:552
void GetSystHistos(const std::string &group, TH2_h *&h1, TH2_h *&h2, TH2_h *&h1w)
Get Histos for updating systematics when using several files.
Definition: HistoStack.cxx:421
std::string _titleY
The title of the Y axis.
Definition: HistoStack.hxx:176
std::string _titleX
The title of the X axis.
Definition: HistoStack.hxx:173
bool CheckInternalOption(const std::string &uopt, const std::string &this_opt)
Check if specific option appears in option field (don&#39;t check if it exists: Added with AddOption) ...
std::vector< TH1_h * > _histos1D
The TH1_hs that were added to the stack.
Definition: HistoStack.hxx:141
TH2_h * _hall2D
Definition: HistoStack.hxx:167
bool CheckOption(const std::string &uopt, const std::string &this_opt)
Check if specific option exists, and if so if it appears in option field.