ra4_draw  4bd0201e3d922d42bd545d4b045ed44db33454a4
hist2d.cpp
Go to the documentation of this file.
1 #include "core/hist2d.hpp"
2 
3 #include <string>
4 #include <vector>
5 #include <sstream>
6 
7 #include <sys/stat.h>
8 
9 #include "TStyle.h"
10 #include "TH2D.h"
11 #include "TROOT.h"
12 #include "TCanvas.h"
13 #include "TLatex.h"
14 #include "TLegend.h"
15 
16 #include "core/named_func.hpp"
17 
18 using namespace std;
19 using namespace PlotOptTypes;
20 
22  const std::shared_ptr<Process> &process,
23  const TH2D &hist_template):
24  FigureComponent(figure, process),
25  clusterizer_(hist_template, 10000),
26  proc_and_hist_cut_(figure.cut_ && process->cut_),
27  cut_vector_(),
28  wgt_vector_(),
29  xval_vector_(),
30  yval_vector_(){
31 }
32 
34  const Hist2D& hist = static_cast<const Hist2D&>(figure_);
35  size_t min_vec_size;
36  bool have_vec = false;
37 
38  const NamedFunc &cut = proc_and_hist_cut_;
39  if(cut.IsScalar()){
40  if(!cut.GetScalar(baby)) return;
41  }else{
42  cut_vector_ = cut.GetVector(baby);
43  if(!HavePass(cut_vector_)) return;
44  have_vec = true;
45  min_vec_size = cut_vector_.size();
46  }
47 
48  const NamedFunc &wgt = hist.weight_;
49  NamedFunc::ScalarType wgt_scalar = 0.;
50  if(wgt.IsScalar()){
51  wgt_scalar = wgt.GetScalar(baby);
52  }else{
53  wgt_vector_ = wgt.GetVector(baby);
54  if(!have_vec || wgt_vector_.size() < min_vec_size){
55  have_vec = true;
56  min_vec_size = wgt_vector_.size();
57  }
58  }
59 
60  const NamedFunc &xval = hist.xaxis_.var_;
61  NamedFunc::ScalarType xval_scalar = 0.;
62  if(xval.IsScalar()){
63  xval_scalar = xval.GetScalar(baby);
64  }else{
65  xval_vector_ = xval.GetVector(baby);
66  if(!have_vec || xval_vector_.size() < min_vec_size){
67  have_vec = true;
68  min_vec_size = xval_vector_.size();
69  }
70  }
71 
72  const NamedFunc &yval = hist.yaxis_.var_;
73  NamedFunc::ScalarType yval_scalar = 0.;
74  if(yval.IsScalar()){
75  yval_scalar = yval.GetScalar(baby);
76  }else{
77  yval_vector_ = yval.GetVector(baby);
78  if(!have_vec || yval_vector_.size() < min_vec_size){
79  have_vec = true;
80  min_vec_size = yval_vector_.size();
81  }
82  }
83 
84  if(!have_vec){
85  clusterizer_.AddPoint(xval_scalar, yval_scalar, wgt_scalar);
86  }else{
87  for(size_t i = 0; i < min_vec_size; ++i){
88  if(cut.IsVector() && !cut_vector_.at(i)) continue;
89  clusterizer_.AddPoint(xval.IsScalar() ? xval_scalar : xval_vector_.at(i),
90  yval.IsScalar() ? yval_scalar : yval_vector_.at(i),
91  wgt.IsScalar() ? wgt_scalar : wgt_vector_.at(i));
92  }
93  }
94 }
95 
96 Hist2D::Hist2D(const Axis &xaxis, const Axis &yaxis, const NamedFunc &cut,
97  const std::vector<std::shared_ptr<Process> > &processes,
98  const std::vector<PlotOpt> &plot_options):
99  Figure(),
100  xaxis_(xaxis),
101  yaxis_(yaxis),
102  cut_(cut),
103  weight_("weight"),
104  tag_(""),
105  plot_options_(plot_options),
106  backgrounds_(),
107  signals_(),
108  datas_(),
109  this_opt_(PlotOpt()),
110  luminosity_(){
111  string xtitle = xaxis_.title_;
112  if(xaxis.units_ != "") xtitle += " ["+xaxis.units_+"]";
113  string ytitle = yaxis_.title_;
114  if(yaxis.units_ != "") ytitle += " ["+yaxis.units_+"]";
115 
116  TH2D empty("", (";"+xtitle+";"+ytitle).c_str(),
117  xaxis_.Nbins(), &xaxis_.Bins().at(0),
118  yaxis_.Nbins(), &yaxis_.Bins().at(0));
119  empty.SetStats(false);
120  empty.Sumw2(true);
121  for(const auto &process: processes){
122  TH2D hist_template = empty;
123  hist_template.SetFillColor(process->GetFillColor());
124  hist_template.SetFillStyle(process->GetFillStyle());
125  hist_template.SetLineColor(process->GetLineColor());
126  hist_template.SetLineStyle(process->GetLineStyle());
127  hist_template.SetLineWidth(process->GetLineWidth());
128  hist_template.SetMarkerColor(process->GetMarkerColor());
129  hist_template.SetMarkerStyle(process->GetMarkerStyle());
130  hist_template.SetMarkerSize(process->GetMarkerSize());
131  unique_ptr<SingleHist2D> hist(new SingleHist2D(*this, process, hist_template));
132 
133  switch(process->type_){
134  case Process::Type::data:
135  datas_.push_back(move(hist));
136  break;
138  backgrounds_.push_back(move(hist));
139  break;
141  signals_.push_back(move(hist));
142  break;
143  default:
144  break;
145  }
146  }
147 }
148 
149 void Hist2D::Print(double luminosity,
150  const string &subdir){
151  luminosity_ = luminosity;
152  for(const auto &opt: plot_options_){
153  this_opt_ = opt;
155  gStyle->SetColorModelPS(this_opt_.UseCMYK());
156  gROOT->ForceStyle();
157 
158  MakeOnePlot(subdir);
159  }
160 }
161 
162 void Hist2D::MakeOnePlot(const string &subdir){
163  bool bkg_is_hist;
164  switch(this_opt_.Stack()){
165  default:
166  case StackType::signal_overlay:
167  case StackType::signal_on_top:
168  case StackType::data_norm:
169  bkg_is_hist = true;
170  break;
171  case StackType::lumi_shapes:
172  case StackType::shapes:
173  bkg_is_hist = false;
174  break;
175  }
176 
177  const Int_t NRGBs = 5;
178  const Int_t NCont = 999;
179 
180  Double_t stops[NRGBs] = { 0.00, 0.34, 0.61, 0.84, 1.00 };
181  Double_t red[NRGBs] = { 0.71, 0.50, 1.00, 1.00, 1.00 };
182  Double_t green[NRGBs] = { 0.80, 1.00, 1.00, 0.60, 0.50 };
183  Double_t blue[NRGBs] = { 0.95, 1.00, 0.50, 0.40, 0.50 };
184  TColor::CreateGradientColorTable(NRGBs, stops, red, green, blue, NCont);
185  gStyle->SetNumberContours(NCont);
186 
187  TCanvas c("canvas","canvas", this_opt_.CanvasWidth(), this_opt_.CanvasHeight());
188  c.cd();
189  c.SetTicks(1,1);
190  c.SetFillStyle(4000);
191  c.SetMargin(this_opt_.LeftMargin(),
192  bkg_is_hist ? this_opt_.RightMargin() : 0.05,
194  this_opt_.TopMargin());
195  c.SetLogz();
196 
197  vector<TLine> lines = GetLines();
198  vector<shared_ptr<TLatex> > labels = GetLabels(bkg_is_hist);
199  TLegend legend(this_opt_.LeftMargin(), 1.-this_opt_.TopMargin(),
200  bkg_is_hist ? 1.-this_opt_.RightMargin() : 1.-0.05, 1.);
201  legend.SetNColumns(datas_.size() + signals_.size() + (bkg_is_hist ? 0 : backgrounds_.size()));
202  legend.SetBorderSize(0);
203  legend.SetFillStyle(4000);
204 
205  TH2D bkg_hist = GetBkgHist(bkg_is_hist);
206  vector<TGraph> bkg_graphs;
207  if(bkg_is_hist) bkg_graphs.clear();
208  else bkg_graphs = GetGraphs(backgrounds_, true);
209 
210  vector<TGraph> sig_graphs = GetGraphs(signals_, true);
211  vector<TGraph> data_graphs = GetGraphs(datas_, false);
212 
213  for(size_t i = 0; i < datas_.size(); ++i){
214  AddEntry(legend, *datas_.at(i), data_graphs.at(i));
215  }
216  for(size_t i = 0; i < signals_.size(); ++i){
217  AddEntry(legend, *signals_.at(i), sig_graphs.at(i));
218  }
219  if(!bkg_is_hist){
220  for(size_t i = 0; i < backgrounds_.size(); ++i){
221  AddEntry(legend, *backgrounds_.at(i), bkg_graphs.at(i));
222  }
223  }
224 
225  bkg_hist.Draw("axis");
226  if(bkg_is_hist){
227  bkg_hist.Draw("colz same");
228  }else{
229  for(auto &g: bkg_graphs){
230  g.Draw("p");
231  }
232  }
233  for(auto &l: lines){
234  l.Draw();
235  }
236  for(auto &g: data_graphs){
237  g.Draw("p");
238  }
239  for(auto &g: sig_graphs){
240  g.Draw("p");
241  }
242  for(auto &l: labels){
243  l->Draw("same");
244  }
245  legend.Draw("same");
246  bkg_hist.Draw("axis same");
247  if(subdir != "") mkdir(("plots/"+subdir).c_str(), 0777);
248  string base_name = subdir != ""
249  ? "plots/"+subdir+"/"+Name()
250  : "plots/"+Name();
251  for(const auto &ext: this_opt_.FileExtensions()){
252  string full_name = base_name+"__"+this_opt_.TypeString()+'.'+ext;
253  c.Print(full_name.c_str());
254  cout << "open " << full_name << endl;
255  }
256 }
257 
258 TH2D Hist2D::GetBkgHist(bool bkg_is_hist) const{
259  string units = (xaxis_.units_ == yaxis_.units_) ? (xaxis_.units_+"^{2}") : (xaxis_.units_+"*"+yaxis_.units_);
260  string z_title = bkg_is_hist
261  ? ("Simulated Events/(" + ToString(xaxis_.AvgBinWidth()*yaxis_.AvgBinWidth())+" "+units+")")
262  : "";
263  string title = ";"+xaxis_.Title()+";"+yaxis_.Title()+";"+z_title;
264  TH2D h;
265  if(bkg_is_hist && backgrounds_.size() > 0){
266  h = backgrounds_.front()->clusterizer_.GetHistogram(luminosity_);
267  for(size_t i = 1; i < backgrounds_.size(); ++i){
268  TH2D to_add = backgrounds_.at(i)->clusterizer_.GetHistogram(luminosity_);
269  h.Add(&to_add);
270  }
271  }else{
272  h = TH2D("", title.c_str(),
273  xaxis_.Nbins(), &xaxis_.Bins().at(0),
274  yaxis_.Nbins(), &yaxis_.Bins().at(0));
275  }
276  h.SetTitle(title.c_str());
277  h.GetZaxis()->SetTitle(z_title.c_str());
278  h.SetStats(0);
279  h.SetMinimum(this_opt_.LogMinimum());
280  h.SetLabelOffset(0.011);
281  h.SetTitleOffset(this_opt_.XTitleOffset(), "x");
282  h.SetTitleOffset(this_opt_.YTitleOffset(), "y");
283  h.SetTitleOffset(this_opt_.ZTitleOffset(), "z");
284  h.SetLabelSize(this_opt_.LabelSize(), "xyz");
285  h.SetTitleSize(this_opt_.TitleSize(), "xyz");
286  return h;
287 }
288 
289 vector<TGraph> Hist2D::GetGraphs(const vector<unique_ptr<SingleHist2D> > &components,
290  bool lumi_weighted) const{
291  vector<TGraph> graphs(components.size());
292  for(size_t i = 0; i < components.size(); ++i){
293  graphs.at(i) = components.at(i)->clusterizer_.GetGraph(lumi_weighted ? luminosity_ : 1.);
294  graphs.at(i).SetName(components.at(i)->process_->name_.c_str());
295  }
296  return graphs;
297 }
298 
299 vector<TLine> Hist2D::GetLines() const{
300  vector<TLine> lines;
301  for(const auto &v: xaxis_.cut_vals_){
302  lines.emplace_back(v, yaxis_.Bins().front(), v, yaxis_.Bins().back());
303  }
304  for(const auto &v: yaxis_.cut_vals_){
305  lines.emplace_back(xaxis_.Bins().front(), v, xaxis_.Bins().back(), v);
306  }
307  for(auto &l: lines){
308  l.SetLineStyle(2);
309  l.SetLineWidth(4);
310  l.SetLineColor(kBlack);
311  }
312  return lines;
313 }
314 
315 vector<shared_ptr<TLatex> > Hist2D::GetLabels(bool bkg_is_hist) const{
316  float left = this_opt_.LeftMargin()+0.03;
317  float right = bkg_is_hist ? 1.-this_opt_.RightMargin()-0.03 : 1.-0.05-0.03;
318  float top = 1.-this_opt_.TopMargin()-0.03;
319  vector<shared_ptr<TLatex> > labels;
320  string extra;
321  switch(this_opt_.Title()){
322  case TitleType::preliminary: extra = "Preliminary"; break;
323  case TitleType::simulation: extra = "Simulation"; break;
324  case TitleType::supplementary: extra = "Supplementary"; break;
325  case TitleType::data: extra = ""; break;
326  case TitleType::info: extra = ""; break;
327  default:
328  ERROR("Did not understand title type "+to_string(static_cast<int>(this_opt_.Title())));
329  }
330  labels.push_back(make_shared<TLatex>(left, top,
331  ("#font[62]{CMS}#scale[0.76]{#font[52]{ "+extra+"}}").c_str()));
332  labels.back()->SetNDC();
333  labels.back()->SetTextAlign(13);
334  labels.back()->SetTextFont(this_opt_.Font());
335 
336  ostringstream oss;
337  oss << luminosity_ << " fb^{-1} (13 TeV)" << flush;
338  labels.push_back(make_shared<TLatex>(right, top,
339  oss.str().c_str()));
340  labels.back()->SetNDC();
341  labels.back()->SetTextAlign(33);
342  labels.back()->SetTextFont(this_opt_.Font());
343  return labels;
344 }
345 
346 string Hist2D::Name() const{
347  string cut = "";
348  if(cut_.Name() != "1") cut = "__"+cut_.Name();
349 
350  string weight = "";
351  if(weight_.Name() != "weight") weight = "__"+weight_.Name();
352 
353  if(tag_ == ""){
354  return CodeToPlainText(yaxis_.var_.Name()+"__"+xaxis_.var_.Name()+cut+weight);
355  }else{
356  return CodeToPlainText(tag_+"__"+yaxis_.var_.Name()+"__"+xaxis_.var_.Name()+cut+weight);
357  }
358 }
359 
360 Hist2D & Hist2D::Weight(const NamedFunc &weight){
361  weight_ = weight;
362  return *this;
363 }
364 
365 Hist2D & Hist2D::Tag(const std::string &tag){
366  tag_ = tag;
367  return *this;
368 }
369 
370 void Hist2D::AddEntry(TLegend &l, const SingleHist2D &h, const TGraph &g) const{
371  string name = h.process_->name_;
372  ostringstream oss;
373  oss << name;
374  bool print_rho;
375  switch(this_opt_.Title()){
376  case TitleType::info:
377  print_rho = true;
378  break;
379  case TitleType::preliminary:
380  case TitleType::simulation:
381  case TitleType::supplementary:
382  case TitleType::data:
383  default:
384  print_rho = false;
385  break;
386  }
387  if(print_rho){
388  double rho = h.clusterizer_.GetHistogram(1.).GetCorrelationFactor();
389  oss.precision(2);
390  oss << " [#rho=" << rho << "]" << flush;
391  }
392  oss << flush;
393  l.AddEntry(&g, oss.str().c_str(), "p");
394 }
395 
396 set<const Process*> Hist2D::GetProcesses() const{
397  set<const Process*> processes;
398  for(const auto &proc: backgrounds_){
399  processes.insert(proc->process_.get());
400  }
401  for(const auto &proc: signals_){
402  processes.insert(proc->process_.get());
403  }
404  for(const auto &proc: datas_){
405  processes.insert(proc->process_.get());
406  }
407  return processes;
408 }
409 
411  const auto &component_list = GetComponentList(process);
412  for(const auto &component: component_list){
413  if(component->process_.get() == process){
414  return component.get();
415  }
416  }
417  DBG("Could not find histogram for process "+process->name_+".");
418  return nullptr;
419 }
420 
421 const vector<unique_ptr<Hist2D::SingleHist2D> >& Hist2D::GetComponentList(const Process *process){
422  switch(process->type_){
423  case Process::Type::data:
424  return datas_;
426  return backgrounds_;
428  return signals_;
429  default:
430  ERROR("Did not understand process type "+to_string(static_cast<long>(process->type_))+".");
431  return backgrounds_;
432  }
433 }
PlotOpt & TopMargin(double top)
Definition: plot_opt.cpp:260
std::string tag_
Definition: hist2d.hpp:60
std::vector< PlotOpt > plot_options_
Definition: hist2d.hpp:61
NamedFunc::VectorType cut_vector_
Definition: hist2d.hpp:36
#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
std::shared_ptr< Process > process_
Process associated to this part of the figure.
Definition: figure.hpp:23
NamedFunc::VectorType xval_vector_
Definition: hist2d.hpp:36
void Print(double luminosity, const std::string &subdir) override
Definition: hist2d.cpp:149
std::string Title() const
Definition: axis.cpp:58
std::string units_
Units of Axis::var_.
Definition: axis.hpp:40
NamedFunc::VectorType wgt_vector_
Definition: hist2d.hpp:36
std::vector< TGraph > GetGraphs(const std::vector< std::unique_ptr< SingleHist2D > > &components, bool lumi_weighted) const
Definition: hist2d.cpp:289
PlotOpt & LabelSize(double label_size)
Definition: plot_opt.cpp:156
PlotOpt & CanvasWidth(int width)
Definition: plot_opt.cpp:207
std::vector< std::unique_ptr< SingleHist2D > > backgrounds_
Definition: hist2d.hpp:64
std::string Name() const
Definition: hist2d.cpp:346
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
void AddEntry(TLegend &l, const SingleHist2D &h, const TGraph &g) const
Definition: hist2d.cpp:370
double luminosity_
Definition: hist2d.hpp:69
ScalarType GetScalar(const Baby &b) const
Evaluate scalar function with b as argument.
Definition: named_func.cpp:460
STL namespace.
NamedFunc::VectorType yval_vector_
Definition: hist2d.hpp:36
Combines a callable function taking a Baby and returning a scalar or vector with its string represent...
Definition: named_func.hpp:13
const std::vector< std::unique_ptr< SingleHist2D > > & GetComponentList(const Process *process)
Definition: hist2d.cpp:421
NamedFunc proc_and_hist_cut_
Definition: hist2d.hpp:35
Hist2D()=delete
const Figure & figure_
Reference to figure containing this component.
Definition: figure.hpp:22
double ScalarType
Definition: named_func.hpp:15
std::string title_
Axis title without units.
Definition: axis.hpp:39
bool IsScalar() const
Check if scalar function is valid.
Definition: named_func.cpp:442
std::set< const Process * > GetProcesses() const override
Definition: hist2d.cpp:396
TH2D GetHistogram(double luminosity) const
Definition: axis.hpp:12
#define ERROR(x)
Definition: utilities.hpp:17
std::string TypeString() const
Definition: plot_opt.cpp:466
Axis yaxis_
Definition: hist2d.hpp:58
FigureComponent * GetComponent(const Process *process) override
Definition: hist2d.cpp:410
PlotOpt & XTitleOffset(double x_title_offset)
Definition: plot_opt.cpp:165
PlotOpt & ZTitleOffset(double z_title_offset)
Definition: plot_opt.cpp:183
VectorType GetVector(const Baby &b) const
Evaluate vector function with b as argument.
Definition: named_func.cpp:470
NamedFunc var_
Variable to be plotted.
Definition: axis.hpp:38
PlotOpt & Font(int font)
Definition: plot_opt.cpp:377
TH2D GetBkgHist(bool bkg_is_hist) const
Definition: hist2d.cpp:258
std::vector< std::unique_ptr< SingleHist2D > > signals_
Definition: hist2d.hpp:65
Axis & Bins(const std::vector< double > &bins)
Definition: axis.cpp:38
PlotOpt & TitleSize(double title_size)
Definition: plot_opt.cpp:147
void AddPoint(float x, float y, float w)
Definition: clusterizer.cpp:74
std::vector< TLine > GetLines() const
Definition: hist2d.cpp:299
std::string name_
Definition: process.hpp:28
Axis xaxis_
Definition: hist2d.hpp:58
Hist2D & Weight(const NamedFunc &weight)
Definition: hist2d.cpp:360
void RecordEvent(const Baby &baby)
Definition: hist2d.cpp:33
PlotOpt & UseCMYK(bool use_cmyk)
Definition: plot_opt.cpp:395
void MakeSane()
Definition: plot_opt.cpp:489
PlotOpt & BottomMargin(double bottom)
Definition: plot_opt.cpp:251
bool IsVector() const
Check if vectorr function is valid.
Definition: named_func.cpp:450
Type type_
Definition: process.hpp:29
NamedFunc weight_
Definition: hist2d.hpp:59
Clustering::Clusterizer clusterizer_
Definition: hist2d.hpp:24
PlotOpt & LogMinimum(double log_minimum)
Definition: plot_opt.cpp:350
PlotOpt this_opt_
Definition: hist2d.hpp:68
std::size_t Nbins() const
Definition: axis.cpp:33
std::vector< std::shared_ptr< TLatex > > GetLabels(bool bkg_is_hist) const
Definition: hist2d.cpp:315
std::set< double > cut_vals_
Values of HistoDef::var_ for which to plot a line.
Definition: axis.hpp:41
void MakeOnePlot(const std::string &subdir)
Definition: hist2d.cpp:162
PlotOpt & Title(PlotOptTypes::TitleType title_type)
Definition: plot_opt.cpp:111
std::vector< std::unique_ptr< SingleHist2D > > datas_
Definition: hist2d.hpp:66
bool HavePass(const NamedFunc::VectorType &v)
Definition: named_func.cpp:830
PlotOpt & RightMargin(double right)
Definition: plot_opt.cpp:242
std::string ToString(const T &x)
Definition: utilities.hpp:74
Hist2D & Tag(const std::string &tag)
Definition: hist2d.cpp:365
NamedFunc cut_
Definition: hist2d.hpp:59
PlotOpt & YTitleOffset(double y_title_offset)
Definition: plot_opt.cpp:174