ra4_draw  4bd0201e3d922d42bd545d4b045ed44db33454a4
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
hist1d.cpp
Go to the documentation of this file.
1 
31 #include "core/hist1d.hpp"
32 
33 #include <cmath>
34 
35 #include <algorithm>
36 #include <sstream>
37 
38 #include <sys/stat.h>
39 
40 #include "TROOT.h"
41 #include "TStyle.h"
42 #include "TGraphAsymmErrors.h"
43 #include "TMath.h"
44 #include "TLegendEntry.h"
45 
46 #include "core/utilities.hpp"
47 
48 using namespace std;
49 using namespace PlotOptTypes;
50 
51 namespace{
52  class Counter{
53  public:
55  count_(0){
56  }
57 
58  string operator()(){
59  return to_string(count_++);
60  }
61  private:
62  unsigned long count_;
63  } counter;
64 
73  void DrawAll(const vector<unique_ptr<Hist1D::SingleHist1D> > &hists,
74  string &draw_opt, bool reversed = false){
75  if(!reversed){
76  for(auto &hist: hists){
77  hist->scaled_hist_.Draw(draw_opt.c_str());
78  if(!Contains(draw_opt, "same")){
79  draw_opt = draw_opt + " same";
80  }
81  }
82  }else{
83  for(auto h = hists.crbegin(); h != hists.crend(); ++h){
84  auto &hist = *h;
85  hist->scaled_hist_.Draw(draw_opt.c_str());
86  if(!Contains(draw_opt, "same")){
87  draw_opt = draw_opt + " same";
88  }
89  }
90  }
91  }
92 
97  void StripXLabels(TH1D &h){
98  h.GetXaxis()->SetTitle("");
99  h.SetLabelSize(0., "x");
100  h.SetTitleSize(0., "x");
101  }
102 
114  size_t GetLegendIndex(size_t entry, size_t n_entries, size_t n_columns){
115  size_t entries_per_column = n_entries / n_columns;
116  size_t cols_with_extra_entry = n_entries % n_columns;
117  size_t this_col = -1;
118  size_t this_col_end = 0;
119  while(this_col_end <= entry){
120  ++this_col;
121  this_col_end += entries_per_column;
122  if(this_col < cols_with_extra_entry){
123  ++this_col_end;
124  }
125  }
126  return this_col;
127  }
128 }
129 
130 TH1D Hist1D::blank_ = TH1D();
131 
139  const std::shared_ptr<Process> &process,
140  const TH1D &hist):
141  FigureComponent(figure, process),
142  raw_hist_(hist),
143  scaled_hist_(),
144  proc_and_hist_cut_(figure.cut_ && process->cut_),
145  cut_vector_(),
146  wgt_vector_(),
147  val_vector_(){
148  raw_hist_.Sumw2();
149  scaled_hist_.Sumw2();
150 }
151 
153  const Hist1D& stack = static_cast<const Hist1D&>(figure_);
154  size_t min_vec_size;
155  bool have_vec = false;
156 
157  const NamedFunc &cut = proc_and_hist_cut_;
158  if(cut.IsScalar()){
159  if(!cut.GetScalar(baby)) return;
160  }else{
161  cut_vector_ = cut.GetVector(baby);
162  if(!HavePass(cut_vector_)) return;
163  have_vec = true;
164  min_vec_size = cut_vector_.size();
165  }
166 
167  const NamedFunc &wgt = stack.weight_;
168  NamedFunc::ScalarType wgt_scalar = 0.;
169  if(wgt.IsScalar()){
170  wgt_scalar = wgt.GetScalar(baby);
171  }else{
172  wgt_vector_ = wgt.GetVector(baby);
173  if(!have_vec || wgt_vector_.size() < min_vec_size){
174  have_vec = true;
175  min_vec_size = wgt_vector_.size();
176  }
177  }
178 
179  const NamedFunc &val = stack.xaxis_.var_;
180  NamedFunc::ScalarType val_scalar = 0.;
181  if(val.IsScalar()){
182  val_scalar = val.GetScalar(baby);
183  }else{
184  val_vector_ = val.GetVector(baby);
185  if(!have_vec || val_vector_.size() < min_vec_size){
186  have_vec = true;
187  min_vec_size = val_vector_.size();
188  }
189  }
190 
191  if(!have_vec){
192  raw_hist_.Fill(val_scalar, wgt_scalar);
193  }else{
194  for(size_t i = 0; i < min_vec_size; ++i){
195  if(cut.IsVector() && !cut_vector_.at(i)) continue;
196  raw_hist_.Fill(val.IsScalar() ? val_scalar : val_vector_.at(i),
197  wgt.IsScalar() ? wgt_scalar : wgt_vector_.at(i));
198  }
199  }
200 }
201 
215 double Hist1D::SingleHist1D::GetMax(double max_bound,
216  bool include_error_bar,
217  bool include_overflow) const{
218  int start_bin = include_overflow ? 0 : 1;
219  int end_bin = include_overflow ? (scaled_hist_.GetNbinsX()+1) : scaled_hist_.GetNbinsX();
220  double the_max = -numeric_limits<double>::infinity();
221  for(int bin = start_bin; bin <= end_bin; ++bin){
222  double content = scaled_hist_.GetBinContent(bin);
223  if(include_error_bar){
224  content += scaled_hist_.GetBinErrorUp(bin);
225  }
226  if(content > the_max && content < max_bound){
227  the_max = content;
228  }
229  }
230  return the_max;
231 }
232 
246 double Hist1D::SingleHist1D::GetMin(double min_bound,
247  bool include_error_bar,
248  bool include_overflow) const{
249  int start_bin = include_overflow ? 0 : 1;
250  int end_bin = include_overflow ? scaled_hist_.GetNbinsX() : (scaled_hist_.GetNbinsX()+1);
251  double the_min = numeric_limits<double>::infinity();
252  for(int bin = start_bin; bin <= end_bin; ++bin){
253  double content = scaled_hist_.GetBinContent(bin);
254  if(include_error_bar){
255  content -= fabs(scaled_hist_.GetBinErrorLow(bin));
256  }
257  if(content < the_min && content > min_bound){
258  the_min = content;
259  }
260  }
261  return the_min;
262 }
263 
273 Hist1D::Hist1D(const Axis &xaxis, const NamedFunc &cut,
274  const std::vector<std::shared_ptr<Process> > &processes,
275  const std::vector<PlotOpt> &plot_options):
276  Figure(),
277  xaxis_(xaxis),
278  cut_(cut),
279  weight_("weight"),
280  tag_(""),
281  ratio_numerator_(""),
282  ratio_denominator_(""),
283  plot_options_(plot_options),
284  backgrounds_(),
285  signals_(),
286  datas_(),
287  this_opt_(PlotOpt()),
288  luminosity_(),
289  mc_scale_(),
290  mc_scale_error_(){
291  if(plot_options_.size() > 0) this_opt_ = plot_options_.front();
292 
293  string x_title = xaxis_.title_;
294  if(xaxis_.units_ != "") x_title += " ["+xaxis_.units_+"]";
295 
296  TH1D empty("", (";"+x_title+";").c_str(), xaxis_.Nbins(), &xaxis_.Bins().at(0));
297  empty.SetStats(false);
298  empty.Sumw2(true);
299  for(const auto &process: processes){
300  unique_ptr<SingleHist1D> hist(new SingleHist1D(*this, process, empty));
301  hist->raw_hist_.SetFillColor(process->GetFillColor());
302  hist->raw_hist_.SetFillStyle(process->GetFillStyle());
303  hist->raw_hist_.SetLineColor(process->GetLineColor());
304  hist->raw_hist_.SetLineStyle(process->GetLineStyle());
305  hist->raw_hist_.SetLineWidth(process->GetLineWidth());
306  hist->raw_hist_.SetMarkerColor(process->GetMarkerColor());
307  hist->raw_hist_.SetMarkerStyle(process->GetMarkerStyle());
308  hist->raw_hist_.SetMarkerSize(process->GetMarkerSize());
309 
310  switch(process->type_){
311  case Process::Type::data:
312  datas_.push_back(move(hist));
313  break;
315  backgrounds_.push_back(move(hist));
316  break;
318  signals_.push_back(move(hist));
319  break;
320  default:
321  break;
322  }
323  }
324 
325  blank_.SetFillStyle(0);
326  blank_.SetFillColor(kWhite);
327  blank_.SetLineWidth(0);
328  blank_.SetLineColor(kWhite);
329  blank_.SetMarkerSize(0);
330  blank_.SetMarkerColor(kWhite);
331 }
332 
337 void Hist1D::Print(double luminosity,
338  const string &subdir){
339  luminosity_ = luminosity;
340  for(const auto &opt: plot_options_){
341  this_opt_ = opt;
343  gStyle->SetColorModelPS(this_opt_.UseCMYK());
344  gROOT->ForceStyle();
346  SetRanges();
347  ApplyStyles();
349 
350  double bot_min, bot_max;
351  vector<TH1D> bot_plots = GetBottomPlots(bot_min, bot_max);
352  //I don't know why I can't make this in GetBottomPlots...
353  TGraphAsymmErrors bottom_background;
354  if(this_opt_.Bottom() != BottomType::off){
355  bottom_background = TGraphAsymmErrors(&bot_plots.back());
356  bottom_background.SetMinimum(this_opt_.RatioMinimum());
357  bottom_background.SetMaximum(this_opt_.RatioMaximum());
358  bot_plots.pop_back();
359  }
360 
361  TGraphAsymmErrors bkg_error = GetBackgroundError();
362 
364  TLine horizontal = GetBottomHorizontal();
365  vector<TLine> cut_vals = GetCutLines(GetMinDraw(), GetMaxDraw(), true);
366  vector<TLine> bot_cuts = GetCutLines(bot_min, bot_max, false);
367 
368  unique_ptr<TCanvas> full;
369  unique_ptr<TPad> top, bottom;
370  GetPads(full, top, bottom);
371 
372  if(this_opt_.AutoYAxis()) FixYAxis(bot_plots);
373 
374  if(this_opt_.Bottom() != BottomType::off){
375  bottom->cd();
376 
377  string draw_opt = "e0";
378  for(auto &h: bot_plots){
379  h.Draw(draw_opt.c_str());
380  draw_opt = "e0 same";
381  }
382  bottom_background.Draw("2 same");
383 
384  horizontal.Draw("same");
385 
386  bottom->RedrawAxis();
387  bottom->RedrawAxis("g");
388  for(auto &cut: bot_cuts) cut.Draw();
389  }
390 
391  top->cd();
392  if(this_opt_.YAxis() == YAxisType::log) top->SetLogy(true);
393  else top->SetLogy(false);
394 
395  string draw_opt = "hist";
396  DrawAll(backgrounds_, draw_opt);
397  if(this_opt_.ShowBackgroundError() && backgrounds_.size()) bkg_error.Draw("2 same");
398  DrawAll(signals_, draw_opt, true);
399  ReplaceAll(draw_opt, "hist", "ep");
400  DrawAll(datas_, draw_opt, true);
401  for(auto &cut: cut_vals) cut.Draw();
402 
403  vector<shared_ptr<TLegend> > legends = GetLegends();
404  for(auto &legend: legends){
405  legend->Draw();
406  }
407 
408  top->RedrawAxis();
409  top->RedrawAxis("g");
410 
411  vector<shared_ptr<TLatex> > title_text = GetTitleTexts();
412  for(auto &x: title_text){
413  x->Draw();
414  }
415 
416  // Printing values to terminal
417  if(this_opt_.PrintVals()){
418  TH1D *hdata = (datas_.size() ? &(datas_[0]->scaled_hist_) : 0);
419  TH1D *hmc = (backgrounds_.size() ? &(backgrounds_[0]->scaled_hist_) : 0);
420  TH1D *hbot = (bot_plots.size() ? &(bot_plots[0]) : 0);
421  if(hdata==0 || hmc==0 || hbot==0) cout<<"Printing values not supported yet without Data, MC, or ratio"<<endl;
422  else {
423  int digits = floor(log10(max(hdata->GetBinContent(hdata->GetMaximumBin()),
424  hmc->GetBinContent(hmc->GetMaximumBin())))+1.);
426  int edigits = floor(log10(sqrt(max(hdata->GetMaximum(), hmc->GetMaximum())))+1.)+2;
427  cout<<endl<<"Printing values for "<<Name()<<". Data/MC = "
428  <<RoundNumber(hdata->Integral(), 2,hmc->Integral()) <<endl;
429  for(int bin=1; bin<=hdata->GetNbinsX(); bin++){
430  cout<<"Bin "<<setw(5)<<hdata->GetBinLowEdge(bin)<<","<<setw(5)<<hdata->GetBinLowEdge(bin+1)<<": Data = ";
431  cout<<setw(digits)<<hdata->GetBinContent(bin)<<" +- "<<setw(edigits)<<RoundNumber(hdata->GetBinError(bin),1);
432  cout<<", MC = "<<setw(digits+2)<<RoundNumber(hmc->GetBinContent(bin),1)<<" +- "
433  <<setw(edigits)<<RoundNumber(hmc->GetBinError(bin),1);
434  if(this_opt_.Bottom() != BottomType::off)
435  cout<<" -> Ratio = "<<setw(6)<<RoundNumber(hbot->GetBinContent(bin),3)
436  <<" +- "<<setw(5)<<RoundNumber(hbot->GetBinError(bin),3);
437  cout<<endl;
438  } // Loop over histogram bins
439  }
440  }
441 
442  if(subdir != "") mkdir(("plots/"+subdir).c_str(), 0777);
443  string base_name = subdir != ""
444  ? "plots/"+subdir+"/"+Name()
445  : "plots/"+Name();
446  for(const auto &ext: this_opt_.FileExtensions()){
447  string full_name = base_name+"__"+this_opt_.TypeString()+'.'+ext;
448  full->Print(full_name.c_str());
449  cout << "open " << full_name << endl;
450  }
451  }
452 }
453 
454 set<const Process*> Hist1D::GetProcesses() const{
455  set<const Process*> processes;
456  for(const auto &proc: backgrounds_){
457  processes.insert(proc->process_.get());
458  }
459  for(const auto &proc: signals_){
460  processes.insert(proc->process_.get());
461  }
462  for(const auto &proc: datas_){
463  processes.insert(proc->process_.get());
464  }
465  return processes;
466 }
467 
469  const auto &component_list = GetComponentList(process);
470  for(const auto &component: component_list){
471  if(component->process_.get() == process){
472  return component.get();
473  }
474  }
475  DBG("Could not find histogram for process "+process->name_+".");
476  return nullptr;
477 }
478 
479 string Hist1D::Name() const{
480  string cut = "";
481  if(cut_.Name() != "1") cut = "__"+cut_.Name();
482 
483  string weight = "";
484  if(weight_.Name() != "weight") weight = "__"+weight_.Name();
485 
486  if(tag_ == ""){
487  return CodeToPlainText(xaxis_.var_.Name()+cut+weight);
488  }else{
489  return CodeToPlainText(tag_+"__"+xaxis_.var_.Name()+cut+weight);
490  }
491 }
492 
493 string Hist1D::Title() const{
494  bool cut = (cut_.Name() != "" && cut_.Name() != "1");
495  bool weight = weight_.Name() != "weight";
496  if(cut && weight){
497  return CodeToRootTex(cut_.Name())+" (weight="+CodeToRootTex(weight_.Name())+")";
498  }else if(cut){
499  return CodeToRootTex(cut_.Name());
500  }else if(weight){
501  return CodeToRootTex("weight="+weight_.Name());
502  }else{
503  return "";
504  }
505 }
506 
507 Hist1D & Hist1D::Weight(const NamedFunc &weight){
508  weight_ = weight;
509  return *this;
510 }
511 
512 Hist1D & Hist1D::Tag(const string &tag){
513  tag_ = tag;
514  return *this;
515 }
516 
517 Hist1D & Hist1D::RatioTitle(const string &numerator,
518  const string &denominator){
519  ratio_numerator_ = numerator;
520  ratio_denominator_ = denominator;
521  return *this;
522 }
523 
533  MergeOverflow();
534  ScaleHistos();
535  StackHistos();
536  NormalizeHistos();
537 }
538 
543  for(auto &hist: backgrounds_){
544  hist->scaled_hist_ = hist->raw_hist_;
545  hist->scaled_hist_.SetName(("bkg_"+hist->process_->name_+"_"+counter()).c_str());
546  }
547  for(auto &hist: signals_){
548  hist->scaled_hist_ = hist->raw_hist_;
549  hist->scaled_hist_.SetName(("sig_"+hist->process_->name_+"_"+counter()).c_str());
550  }
551  for(auto &hist: datas_){
552  hist->scaled_hist_ = hist->raw_hist_;
553  hist->scaled_hist_.SetName(("dat_"+hist->process_->name_+"_"+counter()).c_str());
554  }
555 }
556 
560  bool underflow = false, overflow = false;
561  switch(this_opt_.Overflow()){
562  default:
563  case OverflowType::none:
564  underflow = false;
565  overflow = false;
566  break;
567  case OverflowType::underflow:
568  underflow = true;
569  overflow = false;
570  break;
571  case OverflowType::overflow:
572  underflow = false;
573  overflow = true;
574  break;
575  case OverflowType::both:
576  underflow = true;
577  overflow = true;
578  break;
579  }
580 
581  for(auto &hist: backgrounds_){
582  ::MergeOverflow(hist->scaled_hist_, underflow, overflow);
583  }
584  for(auto &hist: signals_){
585  ::MergeOverflow(hist->scaled_hist_, underflow, overflow);
586  }
587  for(auto &hist: datas_){
588  ::MergeOverflow(hist->scaled_hist_, underflow, overflow);
589  }
590 }
591 
594 void Hist1D::ScaleHistos() const{
595  for(auto &hist: backgrounds_){
596  AdjustDensityForBinWidth(hist->scaled_hist_);
597  hist->scaled_hist_.Scale(luminosity_);
598  }
599  for(auto &hist: signals_){
600  AdjustDensityForBinWidth(hist->scaled_hist_);
601  hist->scaled_hist_.Scale(luminosity_);
602  }
603  for(auto &hist: datas_){
604  AdjustDensityForBinWidth(hist->scaled_hist_);
605  }
606 }
607 
610 void Hist1D::StackHistos() const{
611  if(this_opt_.Stack() == StackType::signal_overlay
612  || this_opt_.Stack() == StackType::signal_on_top
613  || this_opt_.Stack() == StackType::data_norm){
614  for(size_t ibkg = backgrounds_.size() - 2; ibkg < backgrounds_.size(); --ibkg){
615  backgrounds_.at(ibkg)->scaled_hist_ = backgrounds_.at(ibkg)->scaled_hist_ + backgrounds_.at(ibkg+1)->scaled_hist_;
616  }
617  if(backgrounds_.size() && this_opt_.Stack() == StackType::signal_on_top){
618  for(auto &hist: signals_){
619  hist->scaled_hist_ = hist->scaled_hist_ + backgrounds_.front()->scaled_hist_;
620  }
621  }
622  }
623 }
624 
629  mc_scale_ = 1.;
630  mc_scale_error_ = 1.;
631  if(this_opt_.Stack() == StackType::data_norm){
632  if(datas_.size() == 0 || backgrounds_.size() == 0) return;
633  int nbins = xaxis_.Nbins();
634  double data_error, mc_error;
635  double data_norm = datas_.front()->scaled_hist_.IntegralAndError(0, nbins+1, data_error, "width");
636  double mc_norm = backgrounds_.front()->scaled_hist_.IntegralAndError(0, nbins+1, mc_error, "width");
637  mc_scale_ = data_norm/mc_norm;
638  mc_scale_error_ = hypot(data_norm*mc_error, mc_norm*data_error)/(mc_norm*mc_norm);
639  for(auto &hist: backgrounds_){
640  hist->scaled_hist_.Scale(mc_scale_);
641  }
642  for(auto h = datas_.begin(); h != datas_.end(); ++h){
643  auto &hist = *h;
644  double dumb;
645  double this_integral = hist->scaled_hist_.IntegralAndError(0, nbins+1, dumb, "width");
646  hist->scaled_hist_.Scale(this_integral == 0. ? 1. : data_norm/this_integral);
647  }
648  }else if(this_opt_.Stack() == StackType::shapes){
649  for(auto &hist: backgrounds_){
650  Normalize(hist->scaled_hist_, 100., true);
651  }
652  for(auto &hist: signals_){
653  Normalize(hist->scaled_hist_, 100., true);
654  }
655  for(auto &hist: datas_){
656  Normalize(hist->scaled_hist_, 100., true);
657  }
658  }
659 }
660 
663 void Hist1D::SetRanges() const{
664  double the_min = GetMinDraw();
665  double the_max = GetMaxDraw();
666 
667  double ratio = GetLegendRatio();
668 
669  double top, bottom;
670  switch(this_opt_.YAxis()){
671  default:
672  case YAxisType::linear:
673  bottom = the_min >= 0. ? 0. : the_min;
674  top = bottom+ratio*(the_max-bottom);
675  break;
676  case YAxisType::log:
677  bottom = the_min > this_opt_.LogMinimum() ? the_min : this_opt_.LogMinimum();
678  top = exp(log(bottom)+ratio*(log(the_max)-log(bottom)));
679  break;
680  }
681 
682  for(auto &hist: backgrounds_){
683  hist->scaled_hist_.SetMinimum(bottom);
684  hist->scaled_hist_.SetMaximum(top);
685  }
686  for(auto &hist: signals_){
687  hist->scaled_hist_.SetMinimum(bottom);
688  hist->scaled_hist_.SetMaximum(top);
689  }
690  for(auto &hist: datas_){
691  hist->scaled_hist_.SetMinimum(bottom);
692  hist->scaled_hist_.SetMaximum(top);
693  }
694 }
695 
698 void Hist1D::ApplyStyles() const{
699  for(auto &hist: backgrounds_){
700  StyleHisto(hist->scaled_hist_);
701  }
702  for(auto &hist: signals_){
703  StyleHisto(hist->scaled_hist_);
704  }
705  for(auto &hist: datas_){
706  StyleHisto(hist->scaled_hist_);
707  }
708 }
709 
714 void Hist1D::StyleHisto(TH1D &h) const{
715  h.GetXaxis()->SetTitleOffset(this_opt_.XTitleOffset());
716  h.GetYaxis()->SetTitleOffset(this_opt_.YTitleOffset());
717  h.SetNdivisions(this_opt_.NDivisions(), "xyz");
718  h.SetLabelSize(this_opt_.LabelSize(), "xyz");
719  h.SetTitleSize(this_opt_.TitleSize(), "xyz");
720  h.SetLabelFont(this_opt_.Font(), "xyz");
721  h.SetTitleFont(this_opt_.Font(), "xyz");
722 
723  double bin_width = xaxis_.AvgBinWidth();
724 
725  ostringstream title;
726  switch(this_opt_.Stack()){
727  default:
728  DBG("Unrecognized stack option " << static_cast<int>(this_opt_.Stack()) << ".");
729  case StackType::signal_overlay:
730  case StackType::signal_on_top:
731  case StackType::data_norm:
732  case StackType::lumi_shapes:
733  if(xaxis_.units_ == "" && bin_width == 1){
734  title << "Entries";
735  break;
736  }
737  else{
738  title << "Entries/(" << bin_width;
739  if(xaxis_.units_ != "") title << " " << xaxis_.units_;
740  title << ")";
741  break;
742  }
743  case StackType::shapes:
744  if(xaxis_.units_ == "" && bin_width == 1){
745  title << "% entries";
746  break;
747  }
748  else{
749  title << "% entries/(" << bin_width;
750  if(xaxis_.units_ != "") title << " " << xaxis_.units_;
751  title << ")";
752  break;
753  }
754  }
755 
756  h.GetYaxis()->SetTitle(title.str().c_str());
757 }
758 
762  if(this_opt_.BackgroundsStacked()) return;
763 
764  for(auto &bkg: backgrounds_){
765  TH1D &h = bkg->scaled_hist_;
766  h.SetFillStyle(0);
767  h.SetLineColor(h.GetFillColor());
768  h.SetLineWidth(5);
769  }
770 }
771 
784 void Hist1D::GetPads(unique_ptr<TCanvas> &c,
785  unique_ptr<TPad> &top,
786  unique_ptr<TPad> &bottom) const{
787  c.reset(new TCanvas(("canvas_"+counter()).c_str(), "canvas", this_opt_.CanvasWidth(),
789  c->cd();
790  top.reset(new TPad(("top_pad_"+counter()).c_str(), "top_pad", 0., 0., 1., 1.));
791  bottom.reset(new TPad(("bottom_pad_"+counter()).c_str(), "bottom_pad", 0., 0., 1., 1.));
792  c->SetMargin(0., 0., 0., 0.);
793  c->SetTicks(1,1);
794  c->SetFillStyle(4000);
795  top->SetTicks(1,1);
796  top->SetFillStyle(4000);
797  bottom->SetTicks(1,1);
798  bottom->SetFillStyle(4000);
799  if(this_opt_.Bottom() == BottomType::off){
800  top->SetMargin(this_opt_.LeftMargin(),
803  this_opt_.TopMargin());
804  }else{
805  top->SetMargin(this_opt_.LeftMargin(),
808  this_opt_.TopMargin());
809  bottom->SetMargin(this_opt_.LeftMargin(),
812  1.-this_opt_.BottomHeight());
813  }
814  bottom->Draw();
815  top->Draw();
816 }
817 
823 void Hist1D::FixYAxis(vector<TH1D> &bottom_plots) const{
824  double offset = this_opt_.YTitleOffset();
825  if(this_opt_.YAxis() == YAxisType::log){
826  offset = 1.5;
827  }else{
828  double the_max = GetMaxDraw()*GetLegendRatio();
829  int digits = fabs(floor(log10(the_max))-1)+2;
830  digits = max(2, min(6, digits));//For huge axis scale, reverts to scientific notation
831 
832  //Scale offset by good empirical numbers
833  offset = 0.6+0.25*digits;
834 
835  }
836  for(auto &hist: backgrounds_){
837  hist->scaled_hist_.SetTitleOffset(offset, "y");
838  }
839  for(auto &hist: signals_){
840  hist->scaled_hist_.SetTitleOffset(offset, "y");
841  }
842  for(auto &hist: datas_){
843  hist->scaled_hist_.SetTitleOffset(offset, "y");
844  }
845  for(auto &hist: bottom_plots){
846  if(this_opt_.Bottom() != BottomType::ratio) hist.SetTitleOffset(offset, "y");
847  }
848 }
849 
857 vector<shared_ptr<TLatex> > Hist1D::GetTitleTexts() const{
858  vector<shared_ptr<TLatex> > out;
859  double left = this_opt_.LeftMargin();
860  double right = 1.-this_opt_.RightMargin();
861  double bottom = 1.-this_opt_.TopMargin();
862  double top = 1.;
863  if(this_opt_.Title() == TitleType::info){
864  if(Title() != ""){
865  out.push_back(make_shared<TLatex>(0.5*(left+right), 0.5*(bottom+top),
866  Title().c_str()));
867  out.back()->SetNDC();
868  out.back()->SetTextAlign(22);
869  out.back()->SetTextFont(this_opt_.Font());
870 
871  //Adjust title to fit in available space
872  double max_width, max_height;
873  GetTitleSize(max_width, max_height, true);
874  UInt_t width, height;
875  out.back()->GetBoundingBox(width, height);
876  while(width > max_width || height > max_height){
877  out.back()->SetTextSize(0.8*out.back()->GetTextSize());
878  out.back()->GetBoundingBox(width, height);
879  }
880  while(width < 0.5*max_width && height < 0.5*max_height){
881  out.back()->SetTextSize(1.25*out.back()->GetTextSize());
882  out.back()->GetBoundingBox(width, height);
883  }
884  }
885  }else{
886  string extra;
887  switch(this_opt_.Title()){
888  case TitleType::preliminary: extra = "Preliminary"; break;
889  case TitleType::simulation: extra = "Simulation"; break;
890  case TitleType::supplementary: extra = "Supplementary"; break;
891  case TitleType::data: extra = ""; break;
892  case TitleType::info:
893  default:
894  ERROR("Did not understand title type "+to_string(static_cast<int>(this_opt_.Title())));
895  }
896  out.push_back(make_shared<TLatex>(left, 0.5*(bottom+top),
897  ("#font[62]{CMS}#scale[0.76]{#font[52]{ "+extra+"}}").c_str()));
898  out.back()->SetNDC();
899  out.back()->SetTextAlign(12);
900  out.back()->SetTextFont(this_opt_.Font());
901 
902  ostringstream oss;
903  oss << luminosity_ << " fb^{-1} (13 TeV)" << flush;
904  out.push_back(make_shared<TLatex>(right, 0.5*(bottom+top),
905  oss.str().c_str()));
906  out.back()->SetNDC();
907  out.back()->SetTextAlign(32);
908  out.back()->SetTextFont(this_opt_.Font());
909  }
910  return out;
911 }
912 
917 TGraphAsymmErrors Hist1D::GetBackgroundError() const{
918  TGraphAsymmErrors g;
919  if(backgrounds_.size() == 0){
920  TH1D h("", "", xaxis_.Nbins(), &xaxis_.Bins().at(0));
921  g = TGraphAsymmErrors(&h);
922  }else{
923  g = TGraphAsymmErrors(&(backgrounds_.front()->scaled_hist_));
924  }
925  g.SetFillStyle(3002);
926  // set the color of the error band to the line color, accomodating data-to-data plots
927  g.SetFillColor(backgrounds_.front()->scaled_hist_.GetLineColor());
928  g.SetLineWidth(0);
929  g.SetMarkerSize(0);
930  return g;
931 }
932 
942 vector<TLine> Hist1D::GetCutLines(double y_min, double y_max, bool adjust_bottom) const{
943  double bottom = y_min;
944  if(adjust_bottom){
945  switch(this_opt_.YAxis()){
946  default:
947  DBG("Bad YAxis type " << static_cast<int>(this_opt_.YAxis()));
948  case YAxisType::linear: bottom = y_min >= 0. ? 0. : y_min; break;
949  case YAxisType::log: bottom = y_min > this_opt_.LogMinimum() ? y_min : this_opt_.LogMinimum(); break;
950  }
951  }
952  vector<TLine> out(xaxis_.cut_vals_.size());
953  for(double cut: xaxis_.cut_vals_){
954  out.emplace_back(cut, bottom, cut, y_max);
955  out.back().SetNDC(false);
956  out.back().SetLineStyle(2);
957  out.back().SetLineColor(kBlack);
958  out.back().SetLineWidth(3);
959  }
960 
961  return out;
962 }
963 
973 std::vector<TH1D> Hist1D::GetBottomPlots(double &the_min, double &the_max) const{
974  if(this_opt_.Bottom() == BottomType::off) return vector<TH1D>();
975 
976  TH1D denom;
977  vector<TH1D> out;
978  if(backgrounds_.size() != 0){
979  denom = backgrounds_.front()->scaled_hist_;
980  }else if(datas_.size() != 0){
981  denom = datas_.front()->scaled_hist_;
982  }else if(signals_.size() != 0){
983  denom = signals_.front()->scaled_hist_;
984  }else{
985  ERROR("No histograms available to make bottom plot");
986  }
987  bool stacked;
988  switch(this_opt_.Stack()){
989  case StackType::signal_overlay:
990  case StackType::signal_on_top:
991  case StackType::data_norm:
992  stacked = true; break;
993  case StackType::lumi_shapes:
994  case StackType::shapes:
995  stacked = false; break;
996  default:
997  ERROR("Bad stack type: "+to_string(static_cast<int>(this_opt_.Stack())));
998  break;
999  }
1000  if(stacked && backgrounds_.size()){
1001  out.push_back(backgrounds_.front()->scaled_hist_);
1002  out.back().SetName(("bot_plot_bkg_"+backgrounds_.front()->process_->name_+"_"+counter()).c_str());
1003  }else{
1004  for(const auto &h: backgrounds_){
1005  out.push_back(h->scaled_hist_);
1006  out.back().SetName(("bot_plot_bkg_"+h->process_->name_+"_"+counter()).c_str());
1007  }
1008  }
1009  for(const auto &h: datas_){
1010  out.push_back(h->scaled_hist_);
1011  out.back().SetName(("bot_plot_data_"+h->process_->name_+"_"+counter()).c_str());
1012  }
1013  if(!stacked){
1014  for(const auto &h: signals_){
1015  out.push_back(h->scaled_hist_);
1016  out.back().SetName(("bot_plot_sig_"+h->process_->name_+"_"+counter()).c_str());
1017  }
1018  }
1019  if(!out.size()) return vector<TH1D>();
1020  TH1D band = out.front();
1021  for(size_t i = 0; (i+1) < out.size(); ++i){
1022  out.at(i) = out.at(i+1);
1023  }
1024  out.back() = band;
1025  out.back().SetFillStyle(3002);
1026  // makes ratio error band colored for data-to-data plots as well
1027  if (backgrounds_.front()->scaled_hist_.GetLineColor()!=kBlack)
1028  out.back().SetFillColor(backgrounds_.front()->scaled_hist_.GetLineColor());
1029  out.back().SetLineWidth(0);
1030  out.back().SetMarkerStyle(0);
1031  out.back().SetMarkerSize(0);
1032  out.back().SetName(("bot_plot_band_"+counter()).c_str());
1033 
1034  for(int bin = 0; bin <= denom.GetNbinsX()+1; ++bin){
1035  denom.SetBinError(bin, 0.);
1036  }
1037 
1038  switch(this_opt_.Bottom()){
1039  case BottomType::ratio:
1040  for(auto &h: out){
1041  h.Divide(&denom);
1042  }
1043  break;
1044  case BottomType::diff:
1045  for(auto &h: out){
1046  h = h - denom;
1047  }
1048  break;
1049  case BottomType::off:
1050  default:
1051  ERROR("Bad type for bottom plot: "+to_string(static_cast<int>(this_opt_.Bottom())));
1052  break;
1053  }
1054 
1055  the_min = numeric_limits<double>::infinity();
1056  the_max = -numeric_limits<double>::infinity();
1057  for(auto &h: out){
1058  h.SetNdivisions(this_opt_.NDivisionsBottom(), "y");
1059  for(int bin = 1; bin <= h.GetNbinsX(); ++bin){
1060  double hi = h.GetBinContent(bin)+h.GetBinErrorUp(bin);
1061  double lo = h.GetBinContent(bin)-fabs(h.GetBinErrorLow(bin));
1062  if(hi>the_max) the_max = hi;
1063  if(lo<the_min) the_min = lo;
1064  }
1065  }
1066 
1067  if(this_opt_.Bottom() == BottomType::ratio){
1068  the_min = this_opt_.RatioMinimum();
1069  the_max = this_opt_.RatioMaximum();
1070  for(auto &h: out){
1071  string num = ratio_numerator_;
1072  string den = ratio_denominator_;
1073  if(datas_.size() != 0){
1074  if(num == "") num = "Data";
1075  if(den == "") den = "MC";
1076  }else{
1077  if(num == "") num = "MC";
1078  if(den == "") den = backgrounds_.front()->process_->name_;
1079  }
1080  h.GetYaxis()->CenterTitle();
1081  h.GetYaxis()->SetTitle(("#frac{"+num+"}{"+den+"}").c_str());
1082  h.SetTitleSize(h.GetTitleSize("y")/1.25,"y");
1083  h.SetTitleOffset(h.GetTitleOffset("y")/1.25, "y");
1084  h.SetMinimum(the_min);
1085  h.SetMaximum(the_max);
1086  }
1087  }else if(this_opt_.Bottom() == BottomType::diff){
1088  for(auto &h: out){
1089  if(datas_.size() != 0) h.GetYaxis()->SetTitle("Data-MC");
1090  //else h.GetYaxis()->SetTitle(backgrounds_.front()->process_->name_.c_str());
1091  h.SetMinimum(the_min);
1092  h.SetMaximum(the_max);
1093  h.GetYaxis()->CenterTitle();
1094  }
1095  }
1096  return out;
1097 }
1098 
1106  double left = xaxis_.Bins().front();
1107  double right = xaxis_.Bins().back();
1108  double y;
1109  switch(this_opt_.Bottom()){
1110  case BottomType::ratio: y = 1.; break;
1111  case BottomType::diff: y = 0.; break;
1112  case BottomType::off: y = 0.; break;
1113  default:
1114  y = 0.;
1115  DBG("Invalid BottomType: " << to_string(static_cast<int>(this_opt_.Bottom())));
1116  }
1117 
1118  TLine line(left, y, right, y);
1119  line.SetNDC(false);
1120  line.SetLineStyle(2);
1121  line.SetLineColor(kBlack);
1122  line.SetLineWidth(2);
1123  return line;
1124 }
1125 
1129  if(this_opt_.Bottom() == BottomType::off) return;
1130  for(auto &hist: backgrounds_){
1131  StripXLabels(hist->scaled_hist_);
1132  }
1133  for(auto &hist: signals_){
1134  StripXLabels(hist->scaled_hist_);
1135  }
1136  for(auto &hist: datas_){
1137  StripXLabels(hist->scaled_hist_);
1138  }
1139 }
1140 
1150 double Hist1D::GetMaxDraw(double max_bound) const{
1151  double the_max = -numeric_limits<double>::infinity();
1152  for(const auto &hist: backgrounds_){
1153  double this_max = hist->GetMax(max_bound, this_opt_.ShowBackgroundError());
1154  if(this_max > the_max && this_max < max_bound){
1155  the_max = this_max;
1156  }
1157  }
1158  for(const auto &hist: signals_){
1159  double this_max = hist->GetMax(max_bound, false);
1160  if(this_max > the_max && this_max < max_bound){
1161  the_max = this_max;
1162  }
1163  }
1164  for(const auto &hist: datas_){
1165  double this_max = hist->GetMax(max_bound, true);
1166  if(this_max > the_max && this_max < max_bound){
1167  the_max = this_max;
1168  }
1169  }
1170  return the_max;
1171 }
1172 
1181 double Hist1D::GetMinDraw(double min_bound) const{
1182  double the_min = numeric_limits<double>::infinity();
1183  for(const auto &hist: backgrounds_){
1184  double this_min = hist->GetMin(min_bound, this_opt_.ShowBackgroundError());
1185  if(this_min < the_min && this_min > min_bound){
1186  the_min = this_min;
1187  }
1188  }
1189  for(const auto &hist: signals_){
1190  double this_min = hist->GetMin(min_bound, false);
1191  if(this_min < the_min && this_min > min_bound){
1192  the_min = this_min;
1193  }
1194  }
1195  for(const auto &hist: datas_){
1196  double this_min = hist->GetMin(min_bound, true);
1197  if(this_min < the_min && this_min > min_bound){
1198  the_min = this_min;
1199  }
1200  }
1201  return the_min;
1202 }
1203 
1213 vector<shared_ptr<TLegend> > Hist1D::GetLegends(){
1214  size_t n_entries = datas_.size() + signals_.size() + backgrounds_.size();
1215  if(this_opt_.DisplayLumiEntry()) ++n_entries;
1216  size_t n_columns = min(n_entries, static_cast<size_t>(this_opt_.LegendColumns()));
1217 
1218  double left = this_opt_.LeftMargin()+this_opt_.LegendPad();
1219  double top = 1.-this_opt_.TopMargin()-this_opt_.LegendPad();
1220  double bottom = top-this_opt_.TrueLegendHeight(n_entries);
1221 
1222  double delta_x = this_opt_.TrueLegendWidth(n_entries);
1223  vector<shared_ptr<TLegend> > legends(n_columns);
1224  for(size_t i = 0; i < n_columns; ++i){
1225  double x = left+i*delta_x;
1226  legends.at(i) = make_shared<TLegend>(x, bottom, x+this_opt_.LegendMarkerWidth(), top);
1227  legends.at(i)->SetFillStyle(0);
1228  legends.at(i)->SetBorderSize(0);
1229  legends.at(i)->SetTextSize(this_opt_.TrueLegendEntryHeight(n_entries));
1230  legends.at(i)->SetTextFont(this_opt_.Font());
1231  }
1232 
1233  size_t entries_added = 0;
1234  AddEntries(legends, datas_, "lep", n_entries, entries_added);
1235  AddEntries(legends, signals_, "l", n_entries, entries_added);
1236  AddEntries(legends, backgrounds_, this_opt_.BackgroundsStacked() ? "f" : "l", n_entries, entries_added);
1237 
1238  //Add a dummy legend entry to display MC normalization
1240  auto &leg = legends.at(GetLegendIndex(entries_added, n_entries, legends.size()));
1241  ostringstream label;
1242  label << fixed << setprecision(1) << "L=" << luminosity_ << " fb^{-1}";
1243  if(this_opt_.Stack() == StackType::data_norm && datas_.size() > 0){
1244  label << ", (" << 100.*mc_scale_ << "#pm" << 100.*mc_scale_error_ << ")%";
1245  }
1246  auto entry = leg->AddEntry(&blank_, label.str().c_str(), "f");
1247  entry->SetFillStyle(0);
1248  entry->SetFillColor(kWhite);
1249  entry->SetLineWidth(0);
1250  entry->SetLineColor(kWhite);
1251  entry->SetMarkerStyle(0);
1252  entry->SetMarkerStyle(kWhite);
1253  }
1254 
1255  return legends;
1256 }
1257 
1270 void Hist1D::AddEntries(vector<shared_ptr<TLegend> > &legends,
1271  const vector<unique_ptr<SingleHist1D> > &hists,
1272  const string &style,
1273  size_t n_entries,
1274  size_t &entries_added) const{
1275  for(auto h = hists.cbegin(); h != hists.cend(); ++h){
1276  size_t legend_index = GetLegendIndex(entries_added, n_entries, legends.size());
1277  TLegend &legend = *legends.at(legend_index);
1278  string label = (*h)->process_->name_.c_str();
1279  if(this_opt_.Title() == TitleType::info){
1280  double value;
1281  switch(this_opt_.Stack()){
1282  default:
1283  DBG("Bad stack option: " << static_cast<int>(this_opt_.Stack()));
1284  case StackType::signal_overlay:
1285  case StackType::signal_on_top:
1286  case StackType::data_norm:
1287  value = GetYield(h);
1288  if(value>=1.){
1289  label += " [N=" + FixedDigits(value, 2) + "]";
1290  }else{
1291  label += " [N=" + FixedDigits(value, 1) + "]";
1292  }
1293  break;
1294  case StackType::lumi_shapes:
1295  case StackType::shapes:
1296  value = GetMean(h);
1297  label += " [#mu=" + FixedDigits(value,3) + "]";
1298  break;
1299  }
1300  }
1301  //Shrink text size if label is long
1302  double fudge_factor = 0.25;//Not sure how TLegend width affects marker width, but this seems to work
1303  double max_width = (this_opt_.TrueLegendWidth(n_entries)-this_opt_.LegendMarkerWidth()*fudge_factor) * this_opt_.CanvasWidth();
1304  double max_height = this_opt_.TrueLegendEntryHeight(n_entries) * this_opt_.LegendDensity() * this_opt_.CanvasHeight();
1305  TLatex latex(0.5, 0.5, label.c_str());
1306  latex.SetTextSize(legend.GetTextSize());
1307  latex.SetTextFont(legend.GetTextFont());
1308  UInt_t width, height;
1309  latex.GetBoundingBox(width, height);
1310  while(width > max_width || height > max_height){
1311  latex.SetTextSize(0.95*latex.GetTextSize());
1312  for(auto &leg: legends){
1313  leg->SetTextSize(0.95*leg->GetTextSize());
1314  }
1315  latex.GetBoundingBox(width, height);
1316  }
1317 
1318  legend.AddEntry(&((*h)->scaled_hist_), label.c_str(), style.c_str());
1319  ++entries_added;
1320  }
1321 }
1322 
1328 double Hist1D::GetLegendRatio() const{
1329  size_t num_plots = backgrounds_.size() + signals_.size() + datas_.size();
1330  if(this_opt_.DisplayLumiEntry()) ++num_plots;
1331  double legend_height = this_opt_.TrueLegendHeight(num_plots);
1332  double top_plot_height;
1333  if(this_opt_.Bottom() == BottomType::off){
1334  top_plot_height = 1.-this_opt_.TopMargin()-this_opt_.BottomMargin();
1335  }else{
1336  top_plot_height = 1.-this_opt_.TopMargin()-this_opt_.BottomHeight();
1337  }
1338  return top_plot_height/(top_plot_height-legend_height-2.*this_opt_.LegendPad());
1339 }
1340 
1349 double Hist1D::GetYield(std::vector<std::unique_ptr<SingleHist1D> >::const_iterator h) const{
1350  TH1D hist = (*h)->scaled_hist_;
1351 
1352  //Subtract underlying histogram
1353  if((*h)->process_->type_ == Process::Type::background
1354  && h != (--backgrounds_.cend())
1356  hist = hist - (*(++h))->scaled_hist_;
1357  }
1358 
1359  //Want yield, not area, so divide out average bin width
1360  //N.B.: Can't just use hist.Integral() in case of varying bin width
1361  double raw_integral = hist.Integral("width");
1362  int nbins = hist.GetNbinsX();
1363  double left = hist.GetBinLowEdge(1);
1364  double right = hist.GetBinLowEdge(nbins+1);
1365  double width = (right-left)/nbins;
1366  return raw_integral/width;
1367 }
1368 
1376 double Hist1D::GetMean(std::vector<std::unique_ptr<SingleHist1D> >::const_iterator h) const{
1377  TH1D hist = (*h)->scaled_hist_;
1378 
1379  //Subtract underlying histogram
1380  if((*h)->process_->type_ == Process::Type::background
1381  && h != (--backgrounds_.cend())
1383  hist = hist - (*(++h))->scaled_hist_;
1384  }
1385 
1386  return hist.GetMean();
1387 }
1388 
1398 void Hist1D::GetTitleSize(double &width, double &height, bool in_pixels) const{
1399  width = 1.-this_opt_.LeftMargin()-this_opt_.RightMargin();
1400  height = this_opt_.TopMargin();
1401  if(in_pixels){
1402  width *= this_opt_.CanvasWidth();
1403  height *= this_opt_.CanvasHeight();
1404  }
1405 }
1406 
1407 const vector<unique_ptr<Hist1D::SingleHist1D> >& Hist1D::GetComponentList(const Process *process){
1408  switch(process->type_){
1409  case Process::Type::data:
1410  return datas_;
1412  return backgrounds_;
1413  case Process::Type::signal:
1414  return signals_;
1415  default:
1416  ERROR("Did not understand process type "+to_string(static_cast<long>(process->type_))+".");
1417  return backgrounds_;
1418  }
1419 }
PlotOpt & TopMargin(double top)
Definition: plot_opt.cpp:260
double GetMean(std::vector< std::unique_ptr< SingleHist1D > >::const_iterator h) const
Get mean of histogram.
Definition: hist1d.cpp:1376
#define DBG(x)
Definition: utilities.hpp:18
PlotOpt & Stack(PlotOptTypes::StackType stack_type)
Definition: plot_opt.cpp:120
PlotOpt & FileExtensions(const std::set< std::string > &file_extensions)
Definition: plot_opt.cpp:138
PlotOpt & LeftMargin(double left)
Definition: plot_opt.cpp:233
PlotOpt & YAxis(PlotOptTypes::YAxisType y_axis_type)
Definition: plot_opt.cpp:102
size_t GetLegendIndex(size_t entry, size_t n_entries, size_t n_columns)
Determines which legend column to put an entry in.
Definition: hist1d.cpp:114
PlotOpt & LegendColumns(int columns)
Definition: plot_opt.cpp:278
TLine GetBottomHorizontal() const
Get horizontal line drawn at "agreement" value for bottom plots.
Definition: hist1d.cpp:1105
FigureComponent * GetComponent(const Process *process) final
Definition: hist1d.cpp:468
void SetRanges() const
Set y-axis plotting range.
Definition: hist1d.cpp:663
NamedFunc::VectorType cut_vector_
Definition: hist1d.hpp:52
std::string units_
Units of Axis::var_.
Definition: axis.hpp:40
void StripXLabels(TH1D &h)
Erases x-axis title and labels from plot.
Definition: hist1d.cpp:97
bool DisplayLumiEntry() const
Definition: plot_opt.cpp:461
void Normalize(TH1D &h, double normalization, bool norm_per_avg_x)
Definition: utilities.cpp:290
void ScaleHistos() const
Scales histograms to required luminosity.
Definition: hist1d.cpp:594
std::string Name() const
Definition: hist1d.cpp:479
NamedFunc cut_
Event selection.
Definition: hist1d.hpp:78
PlotOpt & LabelSize(double label_size)
Definition: plot_opt.cpp:156
PlotOpt & CanvasWidth(int width)
Definition: plot_opt.cpp:207
Axis xaxis_
Specification of content: plotted variable, binning, etc.
Definition: hist1d.hpp:77
PlotOpt & AutoYAxis(bool auto_y_axis)
Definition: plot_opt.cpp:192
std::string CodeToPlainText(std::string code)
Definition: utilities.cpp:79
const std::string & Name() const
Get the string representation of this function.
Definition: named_func.cpp:376
double AvgBinWidth() const
Definition: axis.cpp:53
Abstract base class for access to ntuple variables.
Definition: baby.hpp:16
PlotOpt & CanvasHeight(int height)
Definition: plot_opt.cpp:216
std::string tag_
Filename tag to identify plot.
Definition: hist1d.hpp:80
void ReplaceAll(std::string &str, const std::string &orig, const std::string &rep)
Definition: utilities.cpp:52
double GetYield(std::vector< std::unique_ptr< SingleHist1D > >::const_iterator h) const
Get integrated number of weighted entries in histogram.
Definition: hist1d.cpp:1349
Hist1D & Weight(const NamedFunc &weight)
Definition: hist1d.cpp:507
ScalarType GetScalar(const Baby &b) const
Evaluate scalar function with b as argument.
Definition: named_func.cpp:460
STL namespace.
const std::vector< std::unique_ptr< SingleHist1D > > & GetComponentList(const Process *process)
Definition: hist1d.cpp:1407
Combines a callable function taking a Baby and returning a scalar or vector with its string represent...
Definition: named_func.hpp:13
bool Contains(const std::string &str, const std::string &pat)
Definition: utilities.cpp:44
void RecordEvent(const Baby &baby) final
Definition: hist1d.cpp:152
PlotOpt & NDivisionsBottom(int n_divisions)
Definition: plot_opt.cpp:341
std::vector< std::unique_ptr< SingleHist1D > > backgrounds_
Background components of the figure.
Definition: hist1d.hpp:86
const Figure & figure_
Reference to figure containing this component.
Definition: figure.hpp:22
NamedFunc proc_and_hist_cut_
Definition: hist1d.hpp:51
PlotOpt this_opt_
Plot style currently being drawn.
Definition: hist1d.hpp:90
double ScalarType
Definition: named_func.hpp:15
void DrawAll(const vector< unique_ptr< Hist1D::SingleHist1D > > &hists, string &draw_opt, bool reversed=false)
Draws all histograms to current canvas, updating draw_opt to contain "same" as needed.
Definition: hist1d.cpp:73
void NormalizeHistos() const
Normalize histograms to data or 100%*(bin width) if needed for current style.
Definition: hist1d.cpp:628
void Print(double luminosity, const std::string &subdir) final
Produce and save formatted plots at given luminosity.
Definition: hist1d.cpp:337
std::string ratio_numerator_
Label for numerator in ratio plot.
Definition: hist1d.hpp:81
double GetMin(double max_bound=0., bool include_error_bar=false, bool include_overflow=false) const
Definition: hist1d.cpp:246
std::string title_
Axis title without units.
Definition: axis.hpp:39
double mc_scale_
data/MC normalization
Definition: hist1d.hpp:92
double GetMaxDraw(double max_bound=std::numeric_limits< double >::infinity()) const
Get highest drawn point below max_bound across all component histograms.
Definition: hist1d.cpp:1150
bool IsScalar() const
Check if scalar function is valid.
Definition: named_func.cpp:442
std::vector< PlotOpt > plot_options_
Styles with which to draw plot.
Definition: hist1d.hpp:83
std::vector< std::unique_ptr< SingleHist1D > > datas_
Data components of the figure.
Definition: hist1d.hpp:88
PlotOpt & Overflow(PlotOptTypes::OverflowType overflow_type)
Definition: plot_opt.cpp:129
Hist1D & RatioTitle(const std::string &numerator, const std::string &denominator)
Definition: hist1d.cpp:517
double TrueLegendWidth(std::size_t num_entries) const
Definition: plot_opt.cpp:441
NamedFunc::VectorType val_vector_
Definition: hist1d.hpp:52
void RefreshScaledHistos()
Generates stacked and scaled histograms from unstacked and unscaled ones.
Definition: hist1d.cpp:531
Definition: axis.hpp:12
std::string CodeToRootTex(std::string code)
Definition: utilities.cpp:116
std::vector< std::unique_ptr< SingleHist1D > > signals_
Signal components of the figure.
Definition: hist1d.hpp:87
void StyleHisto(TH1D &h) const
Set label styles and title for a histogram.
Definition: hist1d.cpp:714
#define ERROR(x)
Definition: utilities.hpp:17
std::vector< TH1D > GetBottomPlots(double &the_min, double &the_max) const
Get ratio or other plots drawn on the lower pad.
Definition: hist1d.cpp:973
bool BackgroundsStacked() const
Definition: plot_opt.cpp:447
std::string TypeString() const
Definition: plot_opt.cpp:466
Container for a TH1D associated with a single Process.
Definition: hist1d.hpp:25
NamedFunc::VectorType wgt_vector_
Definition: hist1d.hpp:52
void ApplyStyles() const
Set label styles and title for all histograms.
Definition: hist1d.cpp:698
void AddEntries(std::vector< std::shared_ptr< TLegend > > &legends, const std::vector< std::unique_ptr< SingleHist1D > > &hists, const std::string &style, std::size_t n_entries, std::size_t &entries_added) const
Distribute processes from list of histograms across legends.
Definition: hist1d.cpp:1270
double TrueLegendEntryHeight(std::size_t num_entries) const
Definition: plot_opt.cpp:437
std::vector< TLine > GetCutLines(double y_min, double y_max, bool adjust_bottom) const
Get vertical lines at cut values.
Definition: hist1d.cpp:942
PlotOpt & XTitleOffset(double x_title_offset)
Definition: plot_opt.cpp:165
void GetTitleSize(double &width, double &height, bool in_pixels) const
Get width and height of title region.
Definition: hist1d.cpp:1398
std::set< const Process * > GetProcesses() const final
Definition: hist1d.cpp:454
double mc_scale_error_
data/MC normalization uncertainty
Definition: hist1d.hpp:93
void StackHistos() const
Stacks histograms if necessary for current plot style.
Definition: hist1d.cpp:610
VectorType GetVector(const Baby &b) const
Evaluate vector function with b as argument.
Definition: named_func.cpp:470
PlotOpt & NDivisions(int n_divisions)
Definition: plot_opt.cpp:332
NamedFunc var_
Variable to be plotted.
Definition: axis.hpp:38
TString RoundNumber(double num, int decimals, double denom=1.)
Definition: utilities.cpp:361
void FixYAxis(std::vector< TH1D > &bottom_plots) const
Adjust y-axis title offset based on y-axis range.
Definition: hist1d.cpp:823
PlotOpt & Font(int font)
Definition: plot_opt.cpp:377
PlotOpt & Bottom(PlotOptTypes::BottomType bottom_type)
Definition: plot_opt.cpp:93
Hist1D()=delete
Axis & Bins(const std::vector< double > &bins)
Definition: axis.cpp:38
void AdjustFillStyles() const
Make histograms a hollow line for unstacked styles.
Definition: hist1d.cpp:761
PlotOpt & TitleSize(double title_size)
Definition: plot_opt.cpp:147
std::vector< std::shared_ptr< TLegend > > GetLegends()
Get list of legends emulating single legend with multiple columns.
Definition: hist1d.cpp:1213
void MergeOverflow() const
Moves overflow (underflow) contents into last (first) visible bin.
Definition: hist1d.cpp:559
PlotOpt & RatioMaximum(double ratio_maximum)
Definition: plot_opt.cpp:368
std::vector< std::shared_ptr< TLatex > > GetTitleTexts() const
Get text to print at top of plot.
Definition: hist1d.cpp:857
PlotOpt & LegendMarkerWidth(double width)
Definition: plot_opt.cpp:305
std::string name_
Definition: process.hpp:28
PlotOpt & UseCMYK(bool use_cmyk)
Definition: plot_opt.cpp:395
double GetMax(double max_bound=std::numeric_limits< double >::infinity(), bool include_error_bar=false, bool include_overflow=false) const
Definition: hist1d.cpp:215
PlotOpt & ShowBackgroundError(bool show_background_error)
Definition: plot_opt.cpp:386
void MakeSane()
Definition: plot_opt.cpp:489
void AdjustDensityForBinWidth(TH1D &h)
Definition: utilities.cpp:273
TH1D scaled_hist_
Kludge. Mutable storage of scaled and stacked histogram.
Definition: hist1d.hpp:33
PlotOpt & BottomMargin(double bottom)
Definition: plot_opt.cpp:251
bool IsVector() const
Check if vectorr function is valid.
Definition: named_func.cpp:450
A full 1D plot with stacked/overlayed histograms.
Definition: hist1d.hpp:23
void GetPads(std::unique_ptr< TCanvas > &c, std::unique_ptr< TPad > &top, std::unique_ptr< TPad > &bottom) const
Generated canvas and pads for top and bottom plots.
Definition: hist1d.cpp:784
double luminosity_
Luminosity currently being drawn.
Definition: hist1d.hpp:91
Type type_
Definition: process.hpp:29
class anonymous_namespace{hist1d.cpp}::Counter counter
PlotOpt & LegendDensity(double density)
Definition: plot_opt.cpp:323
std::string ratio_denominator_
Label for denominator in ratio plot.
Definition: hist1d.hpp:82
TH1D raw_hist_
Histogram storing distribution before stacking and luminosity weighting.
Definition: hist1d.hpp:32
std::string Title() const
Definition: hist1d.cpp:493
PlotOpt & LegendPad(double pad)
Definition: plot_opt.cpp:314
PlotOpt & LogMinimum(double log_minimum)
Definition: plot_opt.cpp:350
PlotOpt & PrintVals(bool print_vals)
Definition: plot_opt.cpp:404
std::size_t Nbins() const
Definition: axis.cpp:33
double TrueLegendHeight(std::size_t num_entries) const
Definition: plot_opt.cpp:433
std::set< double > cut_vals_
Values of HistoDef::var_ for which to plot a line.
Definition: axis.hpp:41
std::string FixedDigits(double x, int n_digits)
Definition: utilities.cpp:316
Hist1D & Tag(const std::string &tag)
Definition: hist1d.cpp:512
void StripTopPlotLabels() const
Definition: hist1d.cpp:1128
PlotOpt & Title(PlotOptTypes::TitleType title_type)
Definition: plot_opt.cpp:111
PlotOpt & RatioMinimum(double ratio_minimum)
Definition: plot_opt.cpp:359
static TH1D blank_
Definition: hist1d.hpp:94
NamedFunc weight_
Event weight.
Definition: hist1d.hpp:79
void InitializeHistos() const
Sets all Hist1D::SingleHist1D::scaled_hist_ to corresponding Hist1D::SingleHist1D::raw_hist_.
Definition: hist1d.cpp:542
bool HavePass(const NamedFunc::VectorType &v)
Definition: named_func.cpp:830
PlotOpt & RightMargin(double right)
Definition: plot_opt.cpp:242
TGraphAsymmErrors GetBackgroundError() const
Get uncertainty on total background.
Definition: hist1d.cpp:917
double GetMinDraw(double min_bound=0.) const
Get lowest drawn point above min_bound across all component histograms.
Definition: hist1d.cpp:1181
PlotOpt & BottomHeight(double bottom_height)
Definition: plot_opt.cpp:269
double GetLegendRatio() const
Get factor by which to expand y-axis range to fit legend.
Definition: hist1d.cpp:1328
PlotOpt & YTitleOffset(double y_title_offset)
Definition: plot_opt.cpp:174