ra4_draw  4bd0201e3d922d42bd545d4b045ed44db33454a4
table.cpp
Go to the documentation of this file.
1 #include "core/table.hpp"
2 
3 #include <fstream>
4 #include <iomanip>
5 
6 #include <sys/stat.h>
7 
8 #include "RooStats/NumberCountingUtils.h"
9 #include "TH1D.h"
10 #include "TCanvas.h"
11 #include "TPie.h"
12 #include "TLegend.h"
13 #include "TStyle.h"
14 #include "TString.h"
15 
16 #include "core/utilities.hpp"
17 
18 using namespace std;
19 
20 namespace{
21  std::string ToLatex(std::string x){
22  ReplaceAll(x, "#", "\\");
23  auto pos_1 = x.find("\\");
24  auto pos_2 = x.find("_");
25  auto pos_3 = x.find("^");
26  auto pos_4 = x.find("{");
27  auto pos_5 = x.find("}");
28  if(pos_1 != string::npos
29  || pos_2 != string::npos
30  || pos_3 != string::npos
31  || pos_4 != string::npos
32  || pos_5 != string::npos){
33  x = "$"+x+"$";
34  }
35  return x;
36  }
37 }
38 
40  const shared_ptr<Process> &process):
41  FigureComponent(table, process),
42  sumw_(table.rows_.size(), 0.),
43  sumw2_(table.rows_.size(), 0.),
44  proc_and_table_cut_(table.rows_.size(), process->cut_),
45  cut_vector_(),
46  wgt_vector_(),
47  val_vector_(){
48  for(size_t irow = 0; irow < table.rows_.size(); ++irow){
49  proc_and_table_cut_.at(irow) = table.rows_.at(irow).cut_ && process->cut_;
50  }
51 }
52 
54  const Table& table = static_cast<const Table&>(figure_);
55 
56  bool have_vector;
57  size_t min_vec_size;
58  for(size_t irow = 0; irow < table.rows_.size(); ++irow){
59  have_vector = false;
60  min_vec_size = 0;
61 
62  const TableRow& row = table.rows_.at(irow);
63  if(!row.is_data_row_) continue;
64  const NamedFunc &cut = proc_and_table_cut_.at(irow);
65  const NamedFunc &wgt = row.weight_;
66 
67  if(cut.IsScalar()){
68  if(!cut.GetScalar(baby)) continue;
69 
70  }else{
71  cut_vector_ = cut.GetVector(baby);
72  if(!have_vector || cut_vector_.size() < min_vec_size){
73  have_vector = true;
74  min_vec_size = cut_vector_.size();
75  }
76  }
77 
78  NamedFunc::ScalarType wgt_scalar = 0.;
79  if(wgt.IsScalar()){
80  wgt_scalar = wgt.GetScalar(baby);
81  }else{
82  wgt_vector_ = wgt.GetVector(baby);
83  if(!have_vector || wgt_vector_.size() < min_vec_size){
84  have_vector = true;
85  min_vec_size = wgt_vector_.size();
86  }
87  }
88 
89  if(!have_vector){
90  sumw_.at(irow) += wgt_scalar;
91  sumw2_.at(irow) += wgt_scalar*wgt_scalar;
92  }else{
93  for(size_t iobject = 0; iobject < min_vec_size; ++iobject){
94  NamedFunc::ScalarType this_cut = cut.IsScalar() ? true : cut_vector_.at(iobject);
95  if(!this_cut) continue;
96  NamedFunc::ScalarType this_wgt = wgt.IsScalar() ? wgt_scalar : wgt_vector_.at(iobject);
97  sumw_.at(irow) += this_wgt;
98  sumw2_.at(irow) += this_wgt*this_wgt;
99  }
100  }
101  }
102 }
103 
104 Table::Table(const string &name,
105  const vector<TableRow> &rows,
106  const vector<shared_ptr<Process> > &processes,
107  bool do_zbi,
108  bool print_table,
109  bool print_pie):
110  Figure(),
111  name_(name),
112  rows_(rows),
113  do_zbi_(do_zbi),
114  print_table_(print_table),
115  print_pie_(print_pie),
116  plot_options_({PlotOpt("txt/plot_styles.txt", "Pie")}),
117  backgrounds_(),
118  signals_(),
119  datas_(){
120  for(const auto &process: processes){
121  switch(process->type_){
122  case Process::Type::data:
123  datas_.emplace_back(new TableColumn(*this, process));
124  break;
126  backgrounds_.emplace_back(new TableColumn(*this, process));
127  break;
129  signals_.emplace_back(new TableColumn(*this, process));
130  break;
131  default:
132  break;
133  }
134  }
135 
136 
137 }
138 
139 void Table::Print(double luminosity,
140  const string &subdir){
141  if(!print_table_) return;
142  if(subdir != "") mkdir(("tables/"+subdir).c_str(), 0777);
143  string file_name = subdir != ""
144  ? "tables/"+subdir+"/"+name_+"_lumi_"+ToString(luminosity)+".tex"
145  : "tables/"+name_+"_lumi_"+ToString(luminosity)+".tex";
146  std::ofstream file(file_name);
147  file << fixed << setprecision(1);
148  PrintHeader(file);
149  for(size_t i = 0; i < rows_.size(); ++i){
150  PrintRow(file, i, luminosity);
151  }
152  PrintFooter(file);
153  file << flush;
154  file.close();
155  cout << "pdflatex " << file_name << " &> /dev/null; #./python/texify.py tables" << endl;
156 }
157 
158 vector<GammaParams> Table::Yield(const Process *process, double luminosity) const{
159  if(process->type_ == Process::Type::data) luminosity = 1.;
160  const auto &component_list = GetComponentList(process);
161  const TableColumn *col = nullptr;
162  for(const auto &component: component_list){
163  if(component->process_.get() == process){
164  col = static_cast<const TableColumn *>(component.get());
165  }
166  }
167  if(col == nullptr) return vector<GammaParams>();
168  vector<GammaParams> yields(rows_.size());
169  for(size_t i = 0; i < yields.size(); ++i){
170  yields.at(i).SetYieldAndUncertainty(luminosity*col->sumw_.at(i), luminosity*sqrt(col->sumw2_.at(i)));
171  }
172  return yields;
173 }
174 
175 vector<GammaParams> Table::BackgroundYield(double luminosity) const{
176  vector<GammaParams> yields(rows_.size());
177  auto procs = GetProcesses();
178  for(const auto &proc: procs){
179  if(proc->type_ != Process::Type::background) continue;
180  vector<GammaParams> proc_yields = Yield(proc, luminosity);
181  for(size_t i = 0; i < proc_yields.size(); ++i){
182  yields.at(i) += proc_yields.at(i);
183  }
184  }
185  return yields;
186 }
187 
188 vector<GammaParams> Table::DataYield() const{
189  vector<GammaParams> yields(rows_.size());
190  auto procs = GetProcesses();
191  for(const auto &proc: procs){
192  if(proc->type_ != Process::Type::data) continue;
193  vector<GammaParams> proc_yields = Yield(proc, 1.);
194  for(size_t i = 0; i < proc_yields.size(); ++i){
195  yields.at(i) += proc_yields.at(i);
196  }
197  }
198  return yields;
199 }
200 
201 set<const Process*> Table::GetProcesses() const{
202  set<const Process*> processes;
203  for(const auto &proc: backgrounds_){
204  processes.insert(proc->process_.get());
205  }
206  for(const auto &proc: signals_){
207  processes.insert(proc->process_.get());
208  }
209  for(const auto &proc: datas_){
210  processes.insert(proc->process_.get());
211  }
212  return processes;
213 }
214 
216  const auto &component_list = GetComponentList(process);
217  for(const auto &component: component_list){
218  if(component->process_.get() == process){
219  return component.get();
220  }
221  }
222  DBG("Could not find histogram for process "+process->name_+".");
223  return nullptr;
224 }
225 
226 const vector<unique_ptr<Table::TableColumn> >& Table::GetComponentList(const Process *process) const{
227  switch(process->type_){
228  case Process::Type::data:
229  return datas_;
231  return backgrounds_;
233  return signals_;
234  default:
235  ERROR("Did not understand process type "+to_string(static_cast<long>(process->type_))+".");
236  return backgrounds_;
237  }
238 }
239 void Table::PrintHeader(ofstream &file) const{
240  file << "\\documentclass[10pt,oneside]{report}\n";
241  file << "\\usepackage{graphicx,xspace,amssymb,amsmath,colordvi,colortbl,verbatim,multicol}\n";
242  file << "\\usepackage{multirow, rotating}\n\n";
243 
244  file << "\\begin{document}\n";
245  file << "\\begin{sidewaystable}[tbp!]\n";
246  file << " \\centering\n";
247  file << " \\begin{tabular}{ l";
248 
249  if(backgrounds_.size() > 1){
250  file << " | ";
251  for(size_t i = 0; i < backgrounds_.size(); ++i){
252  file << 'r';
253  }
254  file << " | r";
255  }else if(backgrounds_.size() == 1){
256  file << " | r";
257  }
258 
259  if(datas_.size() > 1){
260  file << " | ";
261  for(size_t i = 0; i < datas_.size(); ++i){
262  file << 'r';
263  }
264  file << " | r";
265  }else if(datas_.size() == 1){
266  file << " | r";
267  }
268 
269  for(size_t i = 0; i < signals_.size(); ++i){
270  if(do_zbi_) file << " | rr";
271  else file << " | r";
272  }
273 
274  file << " }\n";
275  file << " \\hline\\hline\n";
276  file << " Cut";
277 
278  if(backgrounds_.size() > 1){
279  for(size_t i = 0; i < backgrounds_.size(); ++i){
280  file << " & " << ToLatex(backgrounds_.at(i)->process_->name_);
281  }
282  file << " & SM Bkg.";
283  }else if(backgrounds_.size() == 1){
284  file << " & " <<ToLatex(backgrounds_.front()->process_->name_);
285  }
286 
287  if(datas_.size() > 1){
288  file << " & ";
289  for(size_t i = 0; i < datas_.size(); ++i){
290  file << " & " << ToLatex(datas_.at(i)->process_->name_);
291  }
292  file << " & Data Tot.";
293  }else if(datas_.size() == 1){
294  file << " & " << ToLatex(datas_.front()->process_->name_);
295  }
296 
297  for(size_t i = 0; i < signals_.size(); ++i){
298  file << " & " << ToLatex(signals_.at(i)->process_->name_);
299  if(do_zbi_)
300  file << " & $Z_{\\text{Bi}}$";
301  }
302 
303  file << "\\\\\n";
304 }
305 
306 void Table::PrintRow(ofstream &file, size_t irow, double luminosity) const{
307  const TableRow& row = rows_.at(irow);
308  if(row.lines_before_ > 0){
309  file << " ";
310  for(size_t i = 0; i < row.lines_before_; ++i){
311  file << "\\hline";
312  }
313  file << "\n";
314  }
315 
316  if(row.is_data_row_){
317  file << " " << row.label_;
318  if(backgrounds_.size() > 1){
319  for(size_t i = 0; i < backgrounds_.size(); ++i){
320  file << " & " << luminosity*backgrounds_.at(i)->sumw_.at(irow);
321  }
322  file << " & " << luminosity*GetYield(backgrounds_, irow) << "$\\pm$" << luminosity*GetError(backgrounds_, irow);
323  }else if(backgrounds_.size() == 1){
324  file << " & " << luminosity*GetYield(backgrounds_, irow) << "$\\pm$" << luminosity*GetError(backgrounds_, irow);
325  }
326 
327  if(datas_.size() > 1){
328  for(size_t i = 0; i < datas_.size(); ++i){
329  file << " & " << datas_.at(i)->sumw_.at(irow);
330  }
331  file << " & " << GetYield(datas_, irow);
332  }else if(datas_.size() == 1){
333  file << " & " << GetYield(datas_, irow);
334  }
335 
336  for(size_t i = 0; i < signals_.size(); ++i){
337  file << " & " << luminosity*signals_.at(i)->sumw_.at(irow);
338  if(do_zbi_){
339  file << " & " << RooStats::NumberCountingUtils::BinomialExpZ(luminosity*signals_.at(i)->sumw_.at(irow),
340  luminosity*GetYield(backgrounds_, irow),
341  hypot(GetError(backgrounds_, irow)/GetYield(backgrounds_, irow), 0.3));
342  }
343  }
344  }else{
345  file << " \\multicolumn{" << NumColumns() << "}{c}{" << row.label_ << "}";
346  }
347 
348  file << "\\\\\n";
349 
350  if(row.lines_after_ > 0){
351  file << " ";
352  for(size_t i = 0; i < row.lines_after_; ++i){
353  file << "\\hline";
354  }
355  file << "\n";
356  }
357 
358  if(print_pie_) PrintPie(irow, luminosity);
359 } // PrintRow
360 
361 void Table::PrintPie(std::size_t irow, double luminosity) const{
362  size_t Nbkg = backgrounds_.size();
363  float Yield_tt = 0, Yield_tot = luminosity*GetYield(backgrounds_, irow);
364  vector<double> counts(Nbkg);
365  vector<int> colors(Nbkg);
366  vector<const char*> labels(Nbkg);
367  vector<TH1D> histos(Nbkg, TH1D("","",1,-1.,1.));
368  TLegend leg(0., 0., 1., 1.);
369  for(size_t ind = 0; ind < Nbkg; ++ind){
370  counts[ind] = luminosity*backgrounds_.at(ind)->sumw_.at(irow);
371  histos[ind].SetFillColor(backgrounds_.at(ind)->process_->GetFillColor());
372  colors.at(ind) = backgrounds_.at(ind)->process_->GetFillColor();
373  string label = backgrounds_.at(ind)->process_->name_;
374  leg.AddEntry(&histos[ind], label.c_str(), "f");
375  labels.at(ind) = label.c_str();
376  if(Contains(label,"t#bar{t}") && !Contains(label,"t#bar{t}V")) Yield_tt += counts[ind];
377 
378  } // Loop over backgrounds
379 
380  // For now, use only the first PlotOpt in the vector
381  gStyle->SetTitleW(0.95);
382  TCanvas can("", "", plot_options_[0].CanvasWidth(), plot_options_[0].CanvasHeight());
383  can.SetFillColorAlpha(0, 0.);
384  can.SetFillStyle(4000);
385  string plot_name;
386 
387  // Printing legend
388  if(irow==0){
389  leg.Draw();
390  plot_name = "plots/pie_"+name_+"_legend_lumi"+RoundNumber(luminosity,0)+".pdf";
391  can.SaveAs(plot_name.c_str());
392  cout<<" open "<<plot_name<<endl;
393  }
394 
395  // Define piechart
396  TPie pie("", "", Nbkg, &counts.at(0), &colors.at(0), &labels.at(0));
397  pie.SetCircle(0.5, 0.48, 0.35);
398  pie.SetTitle(CodeToRootTex(rows_.at(irow).cut_.Name()+" (N="+RoundNumber(Yield_tot,1).Data()
399  +", t#bar{t}="+RoundNumber(Yield_tt*100,1,Yield_tot).Data()+"%)").c_str());
400 
401  // Printing pie chart with percentages
402  pie.SetLabelFormat("%perc");
403  pie.Draw();
404 <<<<<<< HEAD
405  plot_name = CodeToPlainText("plots/pie_"+name_+"_"+(rows_.at(irow).cut_.Name())+"_perc_lumi"+RoundNumber(luminosity,0).Data()+".pdf");
406 =======
407  plot_name = "plots/pie_"+name_+"_"+CodeToPlainText(rows_.at(irow).cut_.Name())+"_perc_lumi"+RoundNumber(luminosity,0).Data()+".pdf";
408 >>>>>>> b1f888b55e7125d5a772cc4a7067bd650781e35f
409  can.SaveAs(plot_name.c_str());
410  cout<<" open "<<plot_name<<endl;
411 
412 } // PrintPie
413 
414 
415 void Table::PrintFooter(ofstream &file) const{
416  file << " \\hline\n";
417  file << " Cut";
418 
419  if(backgrounds_.size() > 1){
420  for(size_t i = 0; i < backgrounds_.size(); ++i){
421  file << " & " << ToLatex(backgrounds_.at(i)->process_->name_);
422  }
423  file << " & SM Bkg.";
424  }else if(backgrounds_.size() == 1){
425  file << " & " << ToLatex(backgrounds_.front()->process_->name_);
426  }
427 
428  if(datas_.size() > 1){
429  file << " & ";
430  for(size_t i = 0; i < datas_.size(); ++i){
431  file << " & " << ToLatex(datas_.at(i)->process_->name_);
432  }
433  file << " & Data Tot.";
434  }else if(datas_.size() == 1){
435  file << " & " << ToLatex(datas_.front()->process_->name_);
436  }
437 
438  for(size_t i = 0; i < signals_.size(); ++i){
439  file << " & " << ToLatex(signals_.at(i)->process_->name_);
440  if(do_zbi_)
441  file << " & $Z_{\\text{Bi}}$";
442  }
443 
444  file << "\\\\\n";
445  file << " \\hline\\hline\n";
446  file << " \\end{tabular}\n";
447  file << "\\end{sidewaystable}\n";
448  file << "\\end{document}\n";
449 }
450 
451 size_t Table::NumColumns() const{
452  return 1
453  + (backgrounds_.size() <= 1 ? backgrounds_.size() : backgrounds_.size()+1)
454  + (datas_.size() <= 1 ? datas_.size() : datas_.size()+1)
455  + (do_zbi_ ? 2 : 1)*signals_.size();
456 }
457 
458 double Table::GetYield(const vector<unique_ptr<TableColumn> > &columns,
459  size_t irow){
460  double yield = 0.;
461  for(const auto &column: columns){
462  yield += column->sumw_.at(irow);
463  }
464  return yield;
465 }
466 
467 double Table::GetError(const vector<unique_ptr<TableColumn> > &columns,
468  size_t irow){
469  double error = 0.;
470  for(const auto &column: columns){
471  error += column->sumw2_.at(irow);
472  }
473  return sqrt(error);
474 }
void PrintRow(std::ofstream &file, std::size_t irow, double luminosity) const
Definition: table.cpp:306
std::string ToLatex(std::string x)
Definition: table.cpp:21
#define DBG(x)
Definition: utilities.hpp:18
Table()=delete
std::vector< GammaParams > Yield(const Process *process, double luminosity) const
Definition: table.cpp:158
std::set< const Process * > GetProcesses() const final
Definition: table.cpp:201
std::string CodeToPlainText(std::string code)
Definition: utilities.cpp:79
std::vector< double > sumw2_
Definition: table.hpp:25
Abstract base class for access to ntuple variables.
Definition: baby.hpp:16
void ReplaceAll(std::string &str, const std::string &orig, const std::string &rep)
Definition: utilities.cpp:52
ScalarType GetScalar(const Baby &b) const
Evaluate scalar function with b as argument.
Definition: named_func.cpp:460
STL namespace.
bool is_data_row_
Definition: table_row.hpp:28
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
std::size_t NumColumns() const
Definition: table.cpp:451
std::size_t lines_after_
Definition: table_row.hpp:27
double ScalarType
Definition: named_func.hpp:15
void PrintPie(std::size_t irow, double luminosity) const
Definition: table.cpp:361
bool IsScalar() const
Check if scalar function is valid.
Definition: named_func.cpp:442
std::vector< GammaParams > BackgroundYield(double luminosity) const
Definition: table.cpp:175
std::string CodeToRootTex(std::string code)
Definition: utilities.cpp:116
#define ERROR(x)
Definition: utilities.hpp:17
NamedFunc weight_
Definition: table_row.hpp:26
FigureComponent * GetComponent(const Process *process) final
Definition: table.cpp:215
VectorType GetVector(const Baby &b) const
Evaluate vector function with b as argument.
Definition: named_func.cpp:470
const std::vector< std::unique_ptr< TableColumn > > & GetComponentList(const Process *process) const
Definition: table.cpp:226
TString RoundNumber(double num, int decimals, double denom=1.)
Definition: utilities.cpp:361
std::string name_
Definition: process.hpp:28
void PrintFooter(std::ofstream &file) const
Definition: table.cpp:415
Type type_
Definition: process.hpp:29
std::string label_
Definition: table_row.hpp:25
std::vector< TableRow > rows_
Definition: table.hpp:60
std::vector< GammaParams > DataYield() const
Definition: table.cpp:188
Definition: table.hpp:15
static double GetYield(const std::vector< std::unique_ptr< TableColumn > > &columns, std::size_t irow)
Definition: table.cpp:458
void PrintHeader(std::ofstream &file) const
Definition: table.cpp:239
std::vector< double > sumw_
Definition: table.hpp:25
std::size_t lines_before_
Definition: table_row.hpp:27
void Print(double luminosity, const std::string &subdir) final
Definition: table.cpp:139
void RecordEvent(const Baby &baby) final
Definition: table.cpp:53
static double GetError(const std::vector< std::unique_ptr< TableColumn > > &columns, std::size_t irow)
Definition: table.cpp:467
std::string ToString(const T &x)
Definition: utilities.hpp:74