ra4_macros  bede988c286599a3a84b77a4d788ac0a971e89f9
utilities_macros.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 // utilities_macros - Various functions used accross the code
3 //----------------------------------------------------------------------------
4 
5 #ifndef INT_ROOT
6 #include "utilities_macros.hpp"
7 #endif
8 
9 #include <cmath>
10 #include <vector>
11 
12 #include <iostream>
13 #include <string>
14 #include <stdexcept>
15 #include <unistd.h>
16 
17 #include "TChain.h"
18 #include "TH1D.h"
19 #include "TH2D.h"
20 #include "TCanvas.h"
21 #include "TLegend.h"
22 #include "TLatex.h"
23 #include "TLine.h"
24 #include "TString.h"
25 #include "TColor.h"
26 #include "TMath.h"
27 #include "TRandom3.h"
28 #include "TStyle.h"
29 #include "TEfficiency.h"
30 #include "TSystem.h"
31 #include "TDirectory.h"
32 #include "TROOT.h"
33 
34 #include "styles.hpp"
35 #include "utilities.hpp"
36 #include "utilities_macros.hpp"
37 
38 using namespace std;
39 
40 void plot_distributions(vector<sfeats> Samples, vector<hfeats> vars, TString luminosity,
41  TString filetype, TString namestyle, TString dir, bool doRatio, bool showcuts){
42 
43  TString outfolder("plots/"+dir);
44  gSystem->mkdir(outfolder, kTRUE);
45 
46  TString CMStype("");
47  if(namestyle.Contains("_Supplementary")) {
48  CMStype = "Supplementary";
49  namestyle.ReplaceAll("_Supplementary","");
50  }
51  if(namestyle.Contains("_Preliminary")) {
52  CMStype = "Preliminary";
53  namestyle.ReplaceAll("_Preliminary","");
54  }
55 
56  if (doRatio) namestyle = "CMSPaper";
57  styles style(namestyle);
58  if(namestyle.Contains("CMSPaper")) style.nDivisions = 706;
59  if (doRatio){
60  style.LabelSize *= 1.1;
61  style.LegendSize *= 1.0;
62  style.TitleSize *= 1.1;
63  style.yTitleOffset /= 1.3;
64  style.xTitleOffset /= 1.08;
65  }
66  if(showcuts) style.LegendSize *= 0.85;
67  style.setDefaultStyle();
68  TCanvas can;
69  can.cd();
70  TPad *pad(NULL), *bpad(NULL); //bpad (stands for bottom pad) is for ratio
71  if (doRatio){
72  float bpadHeight = 0.3;
73  pad = new TPad("tpad","tpad",0.,bpadHeight,1.,1.); // assign
74  pad->SetBottomMargin(0.02);
75  pad->SetTopMargin(style.PadTopMargin+0.01);
76  pad->Draw();
77  bpad = new TPad("bpad","bpad",0.,0.,1.,bpadHeight+0.005); // assign
78  bpad->SetTopMargin(0.);
79  bpad->SetBottomMargin(2.35*style.PadBottomMargin);
80  bpad->SetFillStyle(4000);
81  bpad->Draw();
82  } else {
83  pad = static_cast<TPad *>(can.cd());
84  }
85 
86  // Reading ntuples
87  vector<TChain *> chain;
88  for(unsigned sam(0); sam < Samples.size(); sam++){
89  chain.push_back(new TChain("tree"));
90  for(unsigned insam(0); insam < Samples[sam].file.size(); insam++){
91  // cout<<"Reading "<<Samples[sam].file[insam]<<endl;
92  chain[sam]->Add(Samples[sam].file[insam]);
93  // cout<<"Entries "<<chain[sam]->GetEntries()<<endl;
94  }
95  }
96 
97  TString lumi_nodot = luminosity; lumi_nodot.ReplaceAll(".","p");
98  TString plot_tag("_lumi"+lumi_nodot+filetype);
99  float minLog = 0.04, fracLeg = 0.36; // Fraction of the histo pad devoted to the legend
100 
101  double legLeft(style.PadLeftMargin+0.03), legRight(1-style.PadRightMargin-0.02);
102  double legY(1-style.PadTopMargin-0.027), legSingle = 0.052;
103  if (doRatio) {legY=1-style.PadTopMargin-0.041; legSingle = 0.06;}
104  double legW = 0.13, legH = legSingle*(vars[0].samples.size()+1)/2;
105  double legX1[] = {legLeft, legLeft+(legRight-legLeft)/2.*1.15};
106  TLegend leg[2]; int nLegs(2);
107  for(int ileg(0); ileg<nLegs; ileg++){
108  leg[ileg].SetX1NDC(legX1[ileg]); leg[ileg].SetX2NDC(legX1[ileg]+legW);
109  leg[ileg].SetY1NDC(legY-legH); leg[ileg].SetY2NDC(legY);
110  leg[ileg].SetTextSize(style.LegendSize); leg[ileg].SetFillColor(0);
111  leg[ileg].SetFillStyle(0); leg[ileg].SetBorderSize(0);
112  leg[ileg].SetTextFont(style.nFont);
113  }
114  TLine line; line.SetLineColor(1); line.SetLineWidth(5); line.SetLineStyle(2);
115  vector< vector<TH1D*> > histo[2];
116  vector<TH1D*> varhisto;
117  vector<float> nentries;
118  TString hname, pname, variable, samVariable, leghisto, totCut, title, ytitle, lumilabel, cmslabel;
119  for(unsigned var(0); var<vars.size(); var++){
120  bool variableBins = vars[var].minx == -1;
121  if (vars[var].minx == -1) vars[var].minx = vars[var].binning[0];
122  const unsigned Nsam(vars[var].samples.size());
123  legH = (Nsam<=3?legSingle*Nsam:legSingle*(Nsam+1)/2);
124  // Calculating fraction of internal pad taken by the legend, and adding a 4% buffer
125  fracLeg = (legH+1-style.PadTopMargin-legY)/(1-style.PadTopMargin-style.PadBottomMargin) + 0.04;
126  for(int ileg(0); ileg<nLegs; ileg++) leg[ileg].SetY1NDC(legY-legH);
127  leg[1].SetX1NDC(legX1[1]+vars[var].moveRLegend); leg[1].SetX2NDC(legX1[1]+legW+vars[var].moveRLegend);
128 
129  cout<<endl;
130 
131  bool someBands = false;
132  // Generating vector of histograms
133  title = cuts2title(vars[var].cuts);
134  if(namestyle.Contains("CMSPaper") && !showcuts) title = "";
135  for(unsigned his(0); his < 2; his++){
136  varhisto.resize(0);
137  for(unsigned sam(0); sam < Nsam; sam++){
138  if(Samples[vars[var].samples[sam]].doBand) someBands = true;
139  hname = "histo"; hname += var; hname += his; hname += sam;
140  delete gROOT->FindObject(hname); // For some reason, the deletion at the end is not enough
141  if(variableBins) {
142  vars[var].minx = vars[var].binning[0];
143  varhisto.push_back(new TH1D(hname, title, vars[var].nbins, vars[var].binning));
144  }else {
145  varhisto.push_back(new TH1D(hname, title, vars[var].nbins, vars[var].minx, vars[var].maxx));
146  }
147  }
148  histo[his].push_back(varhisto);
149  }
150  nentries.resize(Nsam);
151  variable = vars[var].varname;
152  float maxhisto(-999);
153  int nbkg(0);
154  for(unsigned sam(Nsam-1); sam < Nsam; sam--){
155  int isam = vars[var].samples[sam];
156  if(!Samples[isam].isSig && !Samples[isam].isData) nbkg++;
157  samVariable = Samples[isam].samVariable;
158  totCut = Samples[isam].factor+"*"+luminosity+"*weight*("+vars[var].cuts+"&&"+Samples[isam].cut+")";
159  if(Samples[isam].isData) totCut= vars[var].cuts+"&&"+Samples[isam].cut;
160  if(vars[var].PU_reweight && !Samples[isam].isData) totCut = Samples[isam].factor+"*"+luminosity+"*weight*wpu*("+vars[var].cuts+"&&"+Samples[isam].cut+")";
161  //cout<<totCut<<endl;
162  //histo[0][var][sam]->Sumw2();
163  histo[0][var][sam]->SetBinErrorOption(TH1::kPoisson);
164  if(samVariable=="noPlot") chain[isam]->Project(histo[0][var][sam]->GetName(), variable, totCut);
165  else chain[isam]->Project(histo[0][var][sam]->GetName(), samVariable, totCut);
166  if(vars[var].addOverflow)
167  histo[0][var][sam]->SetBinContent(vars[var].nbins,
168  histo[0][var][sam]->GetBinContent(vars[var].nbins)+
169  histo[0][var][sam]->GetBinContent(vars[var].nbins+1));
170 
171 
172  nentries[sam] = histo[0][var][sam]->Integral(1,vars[var].nbins);
173  if(nentries[sam]<0) nentries[sam]=0;
174  ytitle = "Events";
175 
176  if(!namestyle.Contains("CMSPaper") || showcuts) {
177  // ytitle = "Events for "+luminosity+" fb^{-1}";
178  lumilabel = "";
179  cmslabel = "";
180  } else {
181  //lumilabel = TString::Format("L = %1.f",luminosity.Atof()*1000.)+" pb^{-1} (13 TeV)";
182  lumilabel = TString::Format("#scale[0.8]{13 TeV}");
183  cmslabel = "#font[62]{CMS} #scale[0.8]{#font[52]{Simulation}}";
184  if(CMStype=="Supplementary")cmslabel = "#scale[0.8]{#font[62]{CMS}} #scale[0.6]{#font[52]{Supplementary (Simulation)}}";
185  bool contains_data = false;
186  for(unsigned is=0;is<Samples.size();is++){if(Samples[is].isData){contains_data=true; break;} }
187  if(contains_data){
188  cmslabel = "#font[62]{CMS}";
189  cmslabel += " #scale[0.8]{#font[52]{"+CMStype+"}}";
190  lumilabel = TString::Format("%1.1f",luminosity.Atof())+" fb^{-1} (13 TeV)";}
191  }
192  if(vars[var].unit!="") {
193  int digits(0);
194  float binwidth((vars[var].maxx-vars[var].minx)/static_cast<float>(vars[var].nbins));
195  if(binwidth<1) digits = 1;
196  if (!variableBins) ytitle += ("/("+RoundNumber(binwidth,digits) +" "+vars[var].unit+")");
197  }
198  histo[0][var][sam]->SetYTitle(ytitle);
199  // Cloning histos for later
200  for(int bin(0); bin<=histo[0][var][sam]->GetNbinsX()+1; bin++){
201  double val(histo[0][var][sam]->GetBinContent(bin));
202  histo[1][var][sam]->SetBinContent(bin, val);
203  //if(Samples[isam].isData) histo[0][var][sam]->SetBinError(bin, sqrt(val));
204  histo[1][var][sam]->SetBinError(bin, histo[0][var][sam]->GetBinErrorUp(bin));
205  }
206  }
207 
208  if(nbkg>0 && (vars[var].whichPlots.Contains("0") || vars[var].whichPlots.Contains("1")
209  || vars[var].whichPlots.Contains("2"))){
211  int bkgind(-1);
212  unsigned int last_hist=9999;
213  float normalization_ratio=1;
214  for(unsigned sam(Nsam-1); sam < Nsam; sam--){
215  int isam = vars[var].samples[sam];
216  bool noStack = Samples[isam].isSig || Samples[isam].isData;
217  if(!noStack){ // Adding previous bkg histos
218  if(sam<last_hist) last_hist=sam;
219  for(unsigned bsam(sam+1); bsam < Nsam; bsam++){
220  histo[0][var][sam]->Add(histo[0][var][bsam]);
221  break;
222  }
223  histo[0][var][sam]->SetFillStyle(1001);
224  if(Samples[isam].doBand){
225  histo[0][var][sam]->SetFillColor(Samples[isam].color-12);
226  histo[0][var][sam]->SetLineColor(Samples[isam].color);
227  histo[0][var][sam]->SetLineWidth(3);
228  } else {
229  histo[0][var][sam]->SetFillColor(Samples[isam].color);
230  histo[0][var][sam]->SetLineColor(1);
231  histo[0][var][sam]->SetLineWidth(1);
232  }
233  bkgind = sam;
234  } else {
235  histo[0][var][sam]->SetLineColor(Samples[isam].color);
236  if(Samples[isam].isData){
237  histo[0][var][sam]->SetMarkerStyle(20);
238  histo[0][var][sam]->SetMarkerSize(1.2);
239  histo[0][var][sam]->SetLineWidth(2);
240  } else {
241  if(someBands) histo[0][var][sam]->SetLineWidth(3);
242  else histo[0][var][sam]->SetLineWidth(6);
243  histo[0][var][sam]->SetLineStyle(abs(Samples[isam].style));
244  }
245  if(Samples[isam].doStack) histo[0][var][sam]->Add(histo[0][var][bkgind]);
246  }
247 
248  }
249  TString norm_s("");
250  if(vars[var].normalize || doRatio){
251  double err_num(0), err_den(0);
252  float num = histo[0][var][0]->IntegralAndError(1,histo[0][var][0]->GetNbinsX(),err_num);
253  float den = histo[0][var][last_hist]->IntegralAndError(1,histo[0][var][last_hist]->GetNbinsX(),err_den);
254  normalization_ratio = num/den; //I want this to crash if den=0
255  double err_tot(den/num*sqrt(pow(err_num/num,2)+pow(err_den/den,2)));
256  err_tot = num/den*sqrt(pow(err_num/num,2)+pow(err_den/den,2));
257  //cout<<"Histogram [MC] is ("<<RoundNumber((den/num-1)*100,1)
258  // <<" +- "<<RoundNumber(err_tot*100,1)<<")% larger than markers [data]"<<endl;
259  norm_s = "("+RoundNumber((num/den)*100,1)+"#pm"+RoundNumber(err_tot*100,1)+")%";
260  cout<<"Markers [data] are ("<<RoundNumber((num/den)*100,1)
261  <<" +- "<<RoundNumber(err_tot*100,1)<<")% the histogram [MC]. Data yield is "<<num<<endl;
262  }
263 
264  for(unsigned sam(Nsam-1); sam < Nsam; sam--){
265  int isam = vars[var].samples[sam];
266  //bool noStack = Samples[isam].isSig || Samples[isam].isData;
267  if(sam>=last_hist && vars[var].normalize && !Samples[isam].isSig){
268  histo[0][var][sam]->Scale(normalization_ratio);
269  nentries[sam]*= normalization_ratio;
270  }
271 
272  if(Samples[isam].mcerr){ histo[0][var][sam]->SetLineWidth(4); histo[0][var][sam]->SetMarkerStyle(20);
273  //histo[0][var][sam]->SetMarkerColor(Samples[isam].color);
274  histo[0][var][sam]->SetMarkerSize(1.2);
275  histo[0][var][sam]->SetLineStyle(abs(Samples[isam].style));
276  if(Nsam>=3) histo[0][var][2]->SetFillColorAlpha(Samples[2].color, 0.5);
277  }
278  double maxval(histo[0][var][sam]->GetMaximum());
279  if(maxhisto < maxval) maxhisto = maxval;
280  maxval += histo[0][var][sam]->GetBinErrorUp(histo[0][var][sam]->GetMaximumBin());
281  if((Samples[isam].isData || Samples[isam].mcerr) && maxhisto < maxval) maxhisto = maxval;
282  }
283 
284 
285  // First loop over samples
286  pad->cd();
287  for(int ileg(0); ileg<nLegs; ileg++) leg[ileg].Clear();
288  unsigned legcount(0);
289  int firstplotted(-1);
290  for(unsigned sam(0); sam < Nsam; sam++){
291  int isam = vars[var].samples[sam];
292  leghisto = Samples[isam].label;
293  if(!namestyle.Contains("CMSPaper") || showcuts) leghisto += " [N=" + RoundNumber(nentries[sam],0) + "]";
294  //leghisto += " [N=" + RoundNumber(nentries[sam],0) + "]";
295  bool noStack = Samples[isam].isSig || Samples[isam].isData;
296  unsigned ileg = (Nsam<=3?0:legcount>=(Nsam+1)/2);
297  if(!noStack){
298  if(Samples[isam].doBand) leg[ileg].AddEntry(histo[0][var][sam], leghisto,"fl");
299  else leg[ileg].AddEntry(histo[0][var][sam], leghisto,"f");
300  legcount++;
301  if(firstplotted < 0) {
302  if(!Samples[isam].mcerr) {
303  if(!Samples[isam].doBand) histo[0][var][sam]->Draw("hist");
304  else {
305  histo[0][var][sam]->Draw("E2");
306  TString hcname("hclone"); hcname += var;
307  TH1F *hclone = static_cast<TH1F*>(histo[0][var][sam]->Clone(hcname));
308  hclone->SetLineColor(Samples[isam].color);
309  hclone->SetLineWidth(3);
310  hclone->SetFillColor(0);
311  hclone->Draw("hist same");
312  }
313  } else histo[0][var][sam]->Draw("E0LP");
314  firstplotted = sam;
315  style.setTitles(histo[0][var][sam],vars[var].title, ytitle, cmslabel, lumilabel);
316  } else {
317  if(!Samples[isam].mcerr) histo[0][var][sam]->Draw("hist same");
318  else histo[0][var][sam]->Draw("E0LP same");
319  }
320  } else {
321  if(Samples[isam].isSig) leg[ileg].AddEntry(histo[0][var][sam], leghisto,"l");
322  else leg[ileg].AddEntry(histo[0][var][sam], leghisto,"elp");
323  legcount++;
324  }
325  }
326  for(int sam(Nsam-1); sam >= 0; sam--){
327  int isam = vars[var].samples[sam];
328  if(Samples[isam].isSig){if(!Samples[isam].mcerr) histo[0][var][sam]->Draw("hist same"); else histo[0][var][sam]->Draw("EP same"); }
329  if(Samples[isam].isData) histo[0][var][sam]->Draw("e0 same");
330  }
331  for(int ileg(0); ileg<nLegs; ileg++) leg[ileg].Draw();
332 
333  // Setting Y-axis for log_lumi plot
334  if(histo[0][var][firstplotted]->GetMinimum() > minLog) histo[0][var][firstplotted]->SetMinimum(minLog);
335  float maxpadLog(maxhisto*exp(fracLeg*log(maxhisto/minLog)/(1-fracLeg)));
336  histo[0][var][firstplotted]->SetMinimum(minLog);
337  histo[0][var][firstplotted]->SetMaximum(maxpadLog);
338  if (!doRatio) style.moveYAxisLabel(histo[0][var][firstplotted], maxpadLog, true);
339  histo[0][var][firstplotted]->Draw("axis same");
340  if(vars[var].cut>0) line.DrawLine(vars[var].cut, 0, vars[var].cut, maxhisto*1.05);
341 
342  //ratio
343  TH1D* hratio_data(NULL);
344  TLine* l1(NULL);
345  if (doRatio){
346  // TH1D* hratio_mc = static_cast<TH1D*>(histo[0][var][firstplotted]->Clone());
347  TH1D* hdata(NULL);
348  unsigned ndatasam(0);
349  for(unsigned sam(Nsam-1); sam < Nsam; sam--) {
350  int isam = vars[var].samples[sam];
351  if (Samples[isam].isData || (Samples[isam].mcerr && sam==0)) {
352  if (ndatasam==0) hdata = static_cast<TH1D*>(histo[0][var][sam]->Clone());
353  else hdata->Add(histo[0][var][sam]); //in case the different PDs are put in as separate samples
354  ndatasam++;
355  }
356  }
357  if (ndatasam) {
358  float maxRatio = 1.9;
359  if(vars[var].maxRatio > 0) maxRatio = vars[var].maxRatio;
360  hratio_data = static_cast<TH1D*>(hdata->Clone());
361  hratio_data->SetTitle("");
362  hratio_data->Divide(histo[0][var][firstplotted]);
363  hratio_data->GetYaxis()->SetRangeUser(0.1,maxRatio);
364  hratio_data->GetXaxis()->SetLabelOffset(0.025);
365  hratio_data->GetXaxis()->SetLabelSize(style.LabelSize*2.2);
366  hratio_data->GetYaxis()->SetLabelSize(style.LabelSize*2.1);
367  hratio_data->GetYaxis()->SetTitle("Data / MC ");
368  if(Nsam==2) {
369  size_t idata = vars[var].samples[0];
370  if(Samples[idata].label.Contains("2l")) hratio_data->GetYaxis()->SetTitle("2l / 1l");
371  else hratio_data->GetYaxis()->SetTitle("high / low");
372  }
373  hratio_data->GetXaxis()->SetTitle(histo[0][var][firstplotted]->GetXaxis()->GetTitle());
374  hratio_data->GetYaxis()->SetTitleSize(style.TitleSize*3);
375  hratio_data->GetYaxis()->SetTitleOffset(0.5); //can't use relative size, since somehow it changes between plots...
376  hratio_data->GetXaxis()->SetTitleSize(style.TitleSize*3);
377  hratio_data->GetXaxis()->SetTitleOffset(style.xTitleOffset*0.9);
378  //move the labels ou tof the way
379  histo[0][var][firstplotted]->GetXaxis()->SetLabelOffset(2.);
380  //line at 1
381  bpad->cd();
382  hratio_data->Draw("e0");
383  // for (int ko=0; ko< hratio_data->GetNbinsX(); ko++){
384  // cout<<hratio_data->GetBinLowEdge(ko+1)<<" "<<(hratio_data->GetBinLowEdge(ko+1)+hratio_data->GetBinWidth(ko+1))
385  // <<hratio_data->GetBinContent(ko+1)<<std::endl;
386  //}
387 
388  l1 = new TLine(histo[0][var][firstplotted]->GetXaxis()->GetXmin(), 1., histo[0][var][firstplotted]->GetXaxis()->GetXmax(), 1.);
389  l1->SetLineStyle(2);
390  l1->Draw("same");
391  } else {
392  cerr<<"ERROR: Ratio plots currently only supported for plots with data."<<endl;
393  exit(1);
394  }
395  delete hdata;
396  }
397 
398  //label lumi
399  pad->cd();
400  if(!namestyle.Contains("CMSPaper") || showcuts) {
401  TString lumilbl = TString::Format("%1.1f",luminosity.Atof())+" fb^{-1}, "+norm_s;
402  TLatex llbl;
403  llbl.SetTextSize(style.LegendSize*0.8);
404  llbl.SetNDC(); llbl.SetTextAlign(33);
405  llbl.DrawLatex(1-style.PadRightMargin-0.02,leg[0].GetY1NDC()-0.02,lumilbl);
406  }
407  // label nb
408  if(vars[var].tag.Contains("results") && vars[var].cuts.Contains("nbm")){
409  TLatex tla;
410  tla.SetTextSize(0.055);
411  tla.SetTextFont(42);
412  if(vars[var].cuts.Contains("nbm==1")) tla.DrawLatexNDC(0.73,0.64,"#font[62]{N_{b} = 1}");
413  if(vars[var].cuts.Contains("nbm>=2")) tla.DrawLatexNDC(0.73,0.64,"#font[62]{N_{b} #geq 2}");
414  }
415 
416  //save canvas
417  pad->SetLogy(1);
418  pname = outfolder+"/log_lumi_"+vars[var].tag+plot_tag;
419  if(vars[var].normalize) pname.ReplaceAll("/log_lumi","/log_norm");
420  if(!vars[var].skiplog && (vars[var].whichPlots.Contains("0") || vars[var].whichPlots.Contains("1")))
421  can.SaveAs(pname);
422  pad->SetLogy(0);
423 
424  // Setting Y-axis for lumi plot (non-log)
425  float minhisto(0), maxpad(minhisto + (maxhisto-minhisto)/(1-fracLeg));
426  if(vars[var].maxYaxis > 0) maxpad = vars[var].maxYaxis;
427  histo[0][var][firstplotted]->SetMinimum(minhisto);
428  histo[0][var][firstplotted]->SetMaximum(maxpad);
429  // pad = static_cast<TPad *>(can.cd(1));
430  if (!doRatio) style.moveYAxisLabel(histo[0][var][firstplotted], maxpad, false);
431  pname = outfolder+"/lumi_"+vars[var].tag+plot_tag;
432  if(vars[var].normalize) pname.ReplaceAll("/lumi","/norm");
433  if(vars[var].whichPlots.Contains("0") || vars[var].whichPlots.Contains("2")) can.SaveAs(pname);
434  } // Lumi plots
435 
436 
438  maxhisto = -999;
439  for(int ileg(0); ileg<nLegs; ileg++) leg[ileg].Clear();
440  unsigned legcount = 0;
441  for(unsigned sam(0); sam < Nsam; sam++){
442  int isam = vars[var].samples[sam];
443  histo[1][var][sam]->SetLineColor(Samples[isam].color);
444  histo[1][var][sam]->SetMarkerColor(Samples[isam].color);
445  histo[1][var][sam]->SetMarkerStyle(20);
446  histo[1][var][sam]->SetLineStyle(abs(Samples[isam].style));
447  histo[1][var][sam]->SetLineWidth(4);
448  if(nentries[sam]) histo[1][var][sam]->Scale(100./nentries[sam]);
449  if(maxhisto < histo[1][var][sam]->GetMaximum()) maxhisto = histo[1][var][sam]->GetMaximum();
450  style.setTitles(histo[1][var][sam],vars[var].title, "", cmslabel, lumilabel);
451  if(sam==0){
452  histo[1][var][sam]->SetXTitle(vars[var].title);
453  ytitle = "% events";
454  if(vars[var].unit!="") {
455  int digits(0);
456  float binwidth((vars[var].maxx-vars[var].minx)/static_cast<float>(vars[var].nbins));
457  if(binwidth<1) digits = 1;
458  if (!variableBins) ytitle += ("/("+RoundNumber(binwidth,digits) +" "+vars[var].unit+")");
459  }
460  histo[1][var][sam]->SetYTitle(ytitle);
461  if(Samples[isam].style>0) histo[1][var][sam]->Draw("hist");
462  else histo[1][var][sam]->Draw("e0 x0");
463  } else {
464  if(Samples[isam].style>0) histo[1][var][sam]->Draw("hist same");
465  else histo[1][var][sam]->Draw("e0 x0 same");
466  }
467  leghisto = Samples[isam].label;
468  unsigned ileg = (Nsam<=3?0:legcount>=(Nsam+1)/2);
469  if(!namestyle.Contains("CMSPaper") || showcuts){
470  if(vars[var].nevents.at(sam)<0){
471  leghisto += " [#mu=";
472  int digits(0);
473  if(histo[1][var][sam]->GetMean()<30) digits = 1;
474  leghisto += RoundNumber(histo[1][var][sam]->GetMean(),digits) + "]";
475  } else{
476  leg[ileg].SetX1NDC(0.24); leg[ileg].SetX2NDC(0.7);
477  leg[ileg].SetTextSize(0.75*style.LegendSize);
478  if(vars[var].varname.Contains("tks")) leghisto += "[N_{tks} = " + RoundNumber(nentries[sam],1) + ", from N_{events} = "
479  +RoundNumber(vars[var].nevents.at(sam),1)+"]";
480  }
481  }
482 
483  if(Samples[isam].style>0) leg[ileg].AddEntry(histo[1][var][sam], leghisto, "l");
484  else leg[ileg].AddEntry(histo[1][var][sam], leghisto, "p");
485  legcount++;
486  } // Loop over samples
487  for(int ileg(0); ileg<nLegs; ileg++) leg[ileg].Draw();
488  if(vars[var].cut>0) line.DrawLine(vars[var].cut, 0, vars[var].cut, maxhisto*1.05);
489 
490  // Setting Y-axis for shapes plot (non-log)
491  float minhisto(0), maxpad(minhisto + (maxhisto-minhisto)/(1-fracLeg));
492  histo[1][var][0]->SetMinimum(minhisto);
493  histo[1][var][0]->SetMaximum(maxpad);
494  histo[1][var][0]->Draw("axis same");
495  style.moveYAxisLabel(histo[1][var][0], maxpad, false);
496  can.SetLogy(0);
497  if(vars[var].cuts.Contains("abs(isr_tru_pt)")){
498  TLatex tla;
499  tla.SetTextSize(0.055);
500  tla.SetTextFont(42);
501  if(vars[var].cuts.Contains("abs(isr_tru_pt)<10")) tla.DrawLatexNDC(0.63,0.79,"#font[62]{ISR p_{T} < 10 GeV}");
502  if(vars[var].cuts.Contains("abs(isr_tru_pt)>100")) tla.DrawLatexNDC(0.63,0.79,"#font[62]{ISR p_{T} > 100 GeV}");
503  }
504  else if(vars[var].cuts.Contains("nleps<1234")){
505  TString lsp = "{#lower[-0.1]{#tilde{#chi}}#lower[0.2]{#scale[0.85]{^{0}}}#kern[-1.3]{#scale[0.85]{_{1}}}}";
506  TString t1t_label = "#scale[0.95]{#tilde{g}#kern[0.2]{#tilde{g}}, #tilde{g}#rightarrowt#kern[0.18]{#bar{t}}#kern[0.18]"+lsp;
507  TLatex tla;
508  tla.SetTextSize(0.045);
509  tla.SetTextFont(42);
510  tla.DrawLatexNDC(0.52,0.70,"#font[62]{"+t1t_label+" (1500,100)}}");
511  histo[1][var][0]->SetMaximum(60);
512  }
513 
514  pname = outfolder+"/shapes_"+vars[var].tag+plot_tag;
515  if(vars[var].whichPlots.Contains("0") || vars[var].whichPlots.Contains("3")) can.SaveAs(pname);
516  float maxpadLog = maxhisto*exp(fracLeg*log(maxhisto/minLog)/(1-fracLeg));
517  histo[1][var][0]->SetMaximum(maxpadLog);
518  histo[1][var][0]->SetMinimum(minLog);
519  style.moveYAxisLabel(histo[1][var][0], maxpadLog, true);
520  can.SetLogy(1);
521  pname = outfolder+"/log_shapes_"+vars[var].tag+plot_tag;
522  if(!vars[var].skiplog && (vars[var].whichPlots.Contains("0") || vars[var].whichPlots.Contains("4")))
523  can.SaveAs(pname);
524  }// Loop over variables
525  cout<<endl;
526 
527  for(unsigned var(0); var<vars.size(); var++){
528  for(unsigned his(0); his < 2; his++){
529  for(unsigned sam(0); sam < vars[var].samples.size(); sam++)
530  if(histo[his][var][sam]) {
531  //cout<<"Deleting "<<histo[his][var][sam]->GetName()<<endl;
532  delete histo[his][var][sam];
533  }
534  }
535  }
536 }
537 
538 // Right now you have to use full samples, i.e. cuts added to sfeats is ignored (e.g. ntruleps==1 for 1l ttbar)
539 void plot_2D_distributions(vector<sfeats> Samples, vector<hfeats> vars, TString luminosity,
540  TString filetype, TString namestyle, TString dir){
541 
542  TString lumi_nodot = luminosity; lumi_nodot.ReplaceAll(".","p");
543 
544  styles style(namestyle);
545  if(namestyle.Contains("CMSPaper")) style.nDivisions = 706;
546  style.setDefaultStyle();
547  TCanvas can;
548  can.cd();
549  TPad *pad(NULL);
550  pad = static_cast<TPad *>(can.cd());
551  pad->SetRightMargin(0.2);
552  // Reading ntuples
553  vector<TChain *> chain;
554  for(unsigned sam(0); sam < Samples.size(); sam++){
555  chain.push_back(new TChain("tree"));
556  for(unsigned insam(0); insam < Samples[sam].file.size(); insam++){
557  //cout<<"Reading "<<Samples[sam].file[insam]<<endl;
558  chain[sam]->Add(Samples[sam].file[insam]);
559  //cout<<"Entries "<<chain[sam]->GetEntries()<<endl;
560  }
561  }
562 
563  vector<TH2D*> hists;
564  TString hname, title, variable, totCut;
565 
566  // Looping over histograms
567  for(unsigned int i=0; i<vars.size(); i++){
568  hname = "hist"; hname += i;
569  title = cuts2title(vars[i].cuts); title += ";"; title += vars[i].titlex; title += ";"; title += vars[i].titley;
570  variable = vars[i].varnamey+":"+vars[i].varnamex;
571  totCut = luminosity+"*weight*("+vars[i].cuts+")";
572 
573  // Add together chains for the samples that should be in this plot
574 
575  if (isatty(1)) {
576  printf("\rSetting up chain %i of %lu for 2D plots...",i+1,vars.size());
577  fflush(stdout);
578  if(i==vars.size()-1) printf("\n");
579  }
580 
581  //cout<<"Setting up chain "<<i+1<<" of "<<vars.size()<<endl;
582  TChain *tempChain = new TChain("tree");
583  for(unsigned int j=0; j<vars[i].samples.size(); j++){
584  //cout<<"Reading "<<chain[vars[i].samples[j]]<<endl;
585  tempChain->Add(chain[vars[i].samples[j]]);
586  //cout<<"Entries "<<tempChain->GetEntries()<<endl;
587  }
588 
589  //Create and project histogram
590  hists.push_back(new TH2D(hname, title, vars[i].nbinsx,vars[i].minx,vars[i].maxx,vars[i].nbinsy,vars[i].miny,vars[i].maxy));
591  tempChain->Project(hname, variable, totCut, "colz");
592  for(int iby=1;iby<=vars[i].nbinsy;iby++){
593  hists.back()->SetBinContent(vars[i].nbinsx,iby,hists.back()->GetBinContent(vars[i].nbinsx,iby)+hists.back()->GetBinContent(vars[i].nbinsx+1,iby));
594  }
595  for(int ibx=1;ibx<=vars[i].nbinsx;ibx++){
596  hists.back()->SetBinContent(ibx,vars[i].nbinsy,hists.back()->GetBinContent(ibx,vars[i].nbinsy)+hists.back()->GetBinContent(ibx,vars[i].nbinsy+1));
597  }
598 
599  }
600 
601  // Save and format histograms
602  gStyle->SetOptStat("emr");
603  gStyle->SetStatX(0.338); gStyle->SetStatW(0.18); gStyle->SetStatY(0.90); gStyle->SetStatH(0.14);
604 
605  cout<<"Printing 2D plots"<<endl;
606  for(unsigned int doLogz=0; doLogz<2; doLogz++){
607  for(unsigned int i=0; i<vars.size(); i++){
608  if(doLogz==0 && vars[i].whichPlots.Contains("2")) continue;
609  if(doLogz==1 && vars[i].whichPlots.Contains("1")) continue;
610  TString pname;
611  TString plot_tag("_lumi"+lumi_nodot+filetype);
612  hists[i]->SetStats(0);
613  hists[i]->Draw("colz");
614  pname = "plots/"+dir+"/"+vars[i].tag+plot_tag;
615  if(doLogz) pname = "plots/"+dir+"/logz_"+vars[i].tag+plot_tag;
616  can.SetLogz(doLogz);
617  // Draw cut lines
618  if(vars[i].cutx>0 || vars[i].cuty>0){
619  TLine line; line.SetLineColor(1); line.SetLineWidth(6); line.SetLineStyle(2);
620  if(vars[i].cutx>0 && vars[i].cuty>0){
621  line.DrawLine(vars[i].cutx,0,vars[i].cutx,vars[i].cuty);
622  line.DrawLine(0,vars[i].cuty,vars[i].cutx,vars[i].cuty);
623  }
624  else if(vars[i].cutx>0 && vars[i].cuty<0){
625  line.DrawLine(vars[i].cutx,0,vars[i].cutx,vars[i].maxy);
626  }
627  else if(vars[i].cutx<0 && vars[i].cuty>0){
628  line.DrawLine(0,vars[i].cuty,vars[i].maxx,vars[i].cuty);
629  }
630  }
631  can.SaveAs(pname);
632  }
633  }
634  // Delete historgrams
635  for(unsigned int i=0; i<vars.size(); i++){
636  if(hists[i]) hists[i]->Delete();
637  }
638 }
639 
640 TString cuts2title(TString title){
641  if(title=="1") title = "";
642  title.ReplaceAll("1==1", "Full Sample");
643  title.ReplaceAll("el_tks_chg*lep_charge<0", "OS");title.ReplaceAll("mu_tks_chg*lep_charge<0", "OS");title.ReplaceAll("had_tks_chg*lep_charge<0", "OS");
644  title.ReplaceAll("Sum$(abs(mc_id)==11)","n^{true}_{e}");
645  title.ReplaceAll("Sum$(abs(mc_id)==13)","n^{true}_{#mu}");
646  title.ReplaceAll("Sum$(genels_pt>0)", "n^{true}_{e}");
647  title.ReplaceAll("Sum$(genmus_pt>0)", "n^{true}_{#mu}");
648  title.ReplaceAll("Sum$(mus_sigid&&mus_miniso<0.2)","n_{#mu}^{10}");
649  title.ReplaceAll("Sum$(els_sigid&&els_miniso<0.1)","n_{e}^{10}");
650  title.ReplaceAll("nvmus==1&&nmus==1&&nvels==0","1 #mu");
651  title.ReplaceAll("nvmus10==0&&nvels10==0", "0 leptons");
652  title.ReplaceAll("(nmus+nels)", "n_{lep}");
653  title.ReplaceAll("(nels+nmus)", "n_{lep}");
654  title.ReplaceAll("(nvmus+nvels)", "n^{veto}_{lep}");
655  title.ReplaceAll("nvmus==2&&nmus>=1","n_{#mu}#geq1, n^{veto}_{#mu}=2");
656  title.ReplaceAll("nvels==2&&nels>=1","n_{e}#geq1, n^{veto}_{e}=2");
657  title.ReplaceAll("(nvmus>=2||nvels>=2)","n^{veto}_{lep} #geq 2");
658  title.ReplaceAll("(mumu_m*(mumu_m>0)+elel_m*(elel_m>0))>80&&(mumu_m*(mumu_m>0)+elel_m*(elel_m>0))<100",
659  "80<m_{ll}<100");
660  title.ReplaceAll("mumuv_m>80&&mumuv_m<100",
661  "80<m_{ll}<100");
662  title.ReplaceAll("elelv_m>80&&elelv_m<100",
663  "80<m_{ll}<100");
664  title.ReplaceAll("onht>350&&onmet>100&&","");
665  title.ReplaceAll("jets_islep[0]==0","");
666  title.ReplaceAll("(nels==0&&nmus==1)","n_{#mu}=1");
667  title.ReplaceAll("(nels==1&&nmus==0)","n_{#font[12]{e}}=1");
668  title.ReplaceAll("Max$(abs(els_eta)*(els_sigid&&els_miniso<0.1&&els_pt>20))<1.479","barrel #font[12]{e}");
669  title.ReplaceAll("Max$(abs(els_eta)*(els_sigid&&els_miniso<0.1&&els_pt>20))>1.479","endcap #font[12]{e}");
670 
671 
672  title.ReplaceAll("nleps", "n_{l}");
673  title.ReplaceAll("nvleps", "n_{l}");
674  title.ReplaceAll("nmus", "n_{#mu}");
675  title.ReplaceAll("nels", "n_{e}");
676  title.ReplaceAll("nvmus", "n^{veto}_{#mu}");
677  title.ReplaceAll("nvels", "n^{veto}_{e}");
678  title.ReplaceAll("ntruleps", "n^{true}_{l}");
679  title.ReplaceAll("_ra2b", "^{ra2b}");
680  title.ReplaceAll("npv", "n_{PV}");
681  title.ReplaceAll("mumu_pt1", "p_{T}^{#mu}"); title.ReplaceAll("elel_pt1", "p_{T}^{e}");
682 
683  title.ReplaceAll("abs(mc_id)==1000006", "stop"); title.ReplaceAll("abs(mc_id)==1000022", "LSP");
684 
685  title.ReplaceAll("onmet", "MET^{on}"); title.ReplaceAll("onht", "H_{T}^{on}");
686  title.ReplaceAll("njets30","n_{jets}^{30}");
687  title.ReplaceAll("els_pt","p^{e}_{T}"); title.ReplaceAll("mus_pt","p^{#mu}_{T}");
688  title.ReplaceAll("fjets_nconst","n_{const}^{fat jet}");
689  title.ReplaceAll("fjets_30_m[0]","m(J_{1})"); title.ReplaceAll("fjets_m[0]","m(J_{1})");
690  title.ReplaceAll("(fjets_pt*cosh(fjets_eta))","p_{fatjet}"); title.ReplaceAll("fjets_pt","p^{fatjet}_{T}"); title.ReplaceAll("jets_pt","p^{jet}_{T}");
691  title.ReplaceAll("mus_reliso","RelIso"); title.ReplaceAll("els_reliso","RelIso");
692  title.ReplaceAll("mus_miniso_tr15","MiniIso"); title.ReplaceAll("els_miniso_tr15","MiniIso");
693  title.ReplaceAll("njets","n_{jets}");title.ReplaceAll("abs(lep_id)==13&&","");
694  title.ReplaceAll(">=", " #geq "); title.ReplaceAll(">", " > ");
695  title.ReplaceAll("<=", " #leq "); title.ReplaceAll("<", " < ");
696  title.ReplaceAll("&&", ", "); title.ReplaceAll("==", " = ");
697  title.ReplaceAll("met", "MET"); title.ReplaceAll("ht_hlt", "H_{T}^{HLT}");
698  title.ReplaceAll("mht", "MHT");
699  title.ReplaceAll("ht", "H_{T}"); title.ReplaceAll("mt", "m_{T}");
700  title.ReplaceAll("ntks_chg==0", " ITV");
701  title.ReplaceAll("nbm","n_{b}");
702  title.ReplaceAll("nbl","n_{b,l}");
703  title.ReplaceAll("mj", " M_{J}");
704 
705  title.ReplaceAll("el_tks_mt", "Track m_{T}"); title.ReplaceAll("mu_tks_mt", "Track m_{T}"); title.ReplaceAll("had_tks_mt", "Track m_{T}");
706  title.ReplaceAll("el_tks_pt", "Track p_{T}"); title.ReplaceAll("mu_tks_pt", "Track p_{T}"); title.ReplaceAll("had_tks_pt", "Track p_{T}");
707  title.ReplaceAll("el_tks_miniso", "Track miniso"); title.ReplaceAll("mu_tks_miniso", "Track miniso"); title.ReplaceAll("had_tks_miniso", "Track miniso");
708  title.ReplaceAll("el_tks_chg_miniso", "Track charged miniso"); title.ReplaceAll("mu_tks_chg_miniso", "Track charged miniso"); title.ReplaceAll("had_tks_chg_miniso", "Track charged miniso");
709  return title;
710 }
711 
712 TString invertcut(TString cut){ //For only one cut
713  if (cut.Contains("<"))
714  cut.ReplaceAll("<",">=");
715  else if (cut.Contains(">"))
716  cut.ReplaceAll(">","<=");
717  else if (cut.Contains("<="))
718  cut.ReplaceAll("<=",">");
719  else if (cut.Contains(">="))
720  cut.ReplaceAll(">=","<");
721 
722  return cut;
723 }
724 
725 pfeats::pfeats(const vector<int> &isamples, const TString &icut, const TString &itagname):
726  samples(isamples),
727  cut(icut),
728  tagname(itagname){
729  }
730 
731 hfeats::hfeats(TString ivarname, int inbins, float iminx, float imaxx, vector<int> isamples,
732  TString ititle, TString icuts, float icut, TString itagname,bool iskiplog, vector<double> inevents):
733  title(ititle),
734  varname(ivarname),
735  cuts(icuts),
736  nbins(inbins),
737  minx(iminx),
738  maxx(imaxx),
739  cut(icut),
740  samples(isamples),
741  tagname(itagname){
742  format_tag();
743  unit = "";
744  maxYaxis = -1.;
745  maxRatio = -1.;
746  skiplog=iskiplog;
747  if(inevents.at(0)<0) nevents = vector<double>(isamples.size(),-1);
748  else nevents = inevents;
749  if(nevents.size() != samples.size() ) cout<<"hfeats samples/nevents size mismatch: "<<ititle<<endl;
750  whichPlots = "0"; // Make all 4 [log_]lumi and [log_]shapes plots; For 2D: 1=linear, 2=log
751  normalize=false;
752  PU_reweight=false;
753  moveRLegend = 0;
754  addOverflow = true;
755 
756  string ctitle(title.Data()); // Needed because effing TString can't handle square brackets
757  if(!(ctitle.find("GeV")==std::string::npos)) unit = "GeV";
758  if(!(ctitle.find("Number")==std::string::npos)) unit = "";
759  if(!(ctitle.find("phi")==std::string::npos)) unit = "rad";
760  }
761 hfeats::hfeats(TString ivarnamex, TString ivarnamey, int inbinsx, float iminx, float imaxx, int inbinsy, float iminy, float imaxy, vector<int> isamples,
762  TString ititlex, TString ititley, TString icuts, float icutx, float icuty, TString itagname):
763  titlex(ititlex),
764  titley(ititley),
765  varnamex(ivarnamex),
766  varnamey(ivarnamey),
767  cuts(icuts),
768  nbinsx(inbinsx),
769  nbinsy(inbinsy),
770  minx(iminx),
771  maxx(imaxx),
772  miny(iminy),
773  maxy(imaxy),
774  cutx(icutx),
775  cuty(icuty),
776  samples(isamples),
777  tagname(itagname){
778  format_tag();
779  unit = "";
780  maxYaxis = -1.;
781  maxRatio = -1.;
782  PU_reweight=false;
783  addOverflow = true;
784 
785  string ctitle(title.Data()); // Needed because effing TString can't handle square brackets
786  if(!(ctitle.find("GeV")==std::string::npos)) unit = "GeV";
787  if(!(ctitle.find("Number")==std::string::npos)) unit = "";
788  if(!(ctitle.find("phi")==std::string::npos)) unit = "rad";
789  }
790 
791 hfeats::hfeats(TString ivarname, int inbins, float *ibinning, vector<int> isamples,
792  TString ititle, TString icuts, float icut, TString itagname,bool iskiplog, vector<double> inevents):
793  title(ititle),
794  varname(ivarname),
795  cuts(icuts),
796  nbins(inbins),
797  binning(ibinning),
798  cut(icut),
799  samples(isamples),
800  tagname(itagname) {
801  minx = -1; maxx = binning[nbins];
802  format_tag();
803  unit = "";
804  maxYaxis = -1.;
805  maxRatio = -1.;
806  skiplog =iskiplog;
807  if(inevents.at(0)<0) nevents = vector<double>(isamples.size(),-1);
808  else nevents = inevents;
809  if(nevents.size() != samples.size() ) cout<<"hfeats samples/nevents size mismatch: "<<ititle<<endl;
810  whichPlots = "0"; // Make all 4 [log_]lumi and [log_]shapes plots; For 2D: 1=linear, 2=log
811  PU_reweight=false;
812  addOverflow = true;
813  string ctitle(title.Data()); // Needed because effing TString can't handle square brackets
814  if(!(ctitle.find("GeV")==std::string::npos)) unit = "GeV";
815  if(!(ctitle.find("Number")==std::string::npos)) unit = "";
816  if(!(ctitle.find("phi")==std::string::npos)) unit = "rad";
817  }
818 
820  tag = varname;
821  if(varnamex!="" && varnamey!="") tag = varnamex+"_vs_"+varnamey;
822  if(cuts!="1") tag+="_"+cuts;
823  if(tagname!="") tag.Prepend(tagname+"_");
824 
825  tag.ReplaceAll("1==1", "full_sample");
826  tag.ReplaceAll("el_tks_chg*lep_charge<0", "OS");tag.ReplaceAll("mu_tks_chg*lep_charge<0", "OS");tag.ReplaceAll("had_tks_chg*lep_charge<0", "OS");
827  tag.ReplaceAll(".","");
828  tag.ReplaceAll("(",""); tag.ReplaceAll("$",""); tag.ReplaceAll(")","");
829  tag.ReplaceAll("[",""); tag.ReplaceAll("]",""); tag.ReplaceAll("||","_");
830  tag.ReplaceAll("/","_"); tag.ReplaceAll("*",""); tag.ReplaceAll("&&","_");
831  tag.ReplaceAll(">=","ge"); tag.ReplaceAll("<=","se");
832  tag.ReplaceAll(">","g"); tag.ReplaceAll("<","s"); tag.ReplaceAll("=","");
833  tag.ReplaceAll("+",""); tag.ReplaceAll("&","");
834  tag.ReplaceAll("!","not");
835  tag.ReplaceAll("#",""); tag.ReplaceAll("{",""); tag.ReplaceAll("}","");
836 
837  tag.ReplaceAll("htg500_metg200_njetsge7_nbmge1_nmusnels1_","Baseline1B_");
838  tag.ReplaceAll("htg500_metg200_njetsge7_nbmge2_nmusnels1_","Baseline_");
839 
840  tag.ReplaceAll("tks_idlep_chargeg0_nottks_is_primary_tks_idtks_id121_","os_els_");
841  tag.ReplaceAll("tks_idlep_chargeg0_nottks_is_primary_tks_idtks_id169_","os_mus_");
842  tag.ReplaceAll("tks_idlep_charges0_nottks_is_primary_nottks_idtks_id169_tks_idtks_id121_","os_had_");
843 
844  tag.ReplaceAll("nottks_from_w","fakes");
845  tag.ReplaceAll("tks_from_w","prompt");
846 
847  tag.ReplaceAll("tks_ptmintks_mini_netks_mini_ch,tks_r02_netks_r02_ch","abs_mini_iso_chgneu");
848  tag.ReplaceAll("tks_ptmintks_mini_netks_mini_ch,tks_r05_netks_r05_ch","abs_r_05_mini_iso_chgneu");
849  tag.ReplaceAll("tks_pttks_mini_netks_mini_ch","abs_untruncated_mini_iso_chgneu");
850  tag.ReplaceAll("mintks_mini_netks_mini_ch,tks_r02_netks_r02_ch","rel_02_mini_iso_chgneu");
851  tag.ReplaceAll("mintks_mini_netks_mini_ch,tks_r05_netks_r05_ch","rel_05_mini_iso_chgneu");
852  tag.ReplaceAll("tks_mini_netks_mini_ch","rel_untruncated_mini_iso_chgneu");
853 
854  tag.ReplaceAll("tks_ptmintks_mini_ch,tks_r02_ch","abs_mini_iso_chg");
855  tag.ReplaceAll("tks_ptmintks_mini_ch,tks_r05_ch","abs_r05_mini_iso_chg");
856  tag.ReplaceAll("tks_pttks_mini_ch","abs_untruncated_mini_iso_chg");
857  tag.ReplaceAll("mintks_mini_ch,tks_r02_ch","rel_02_mini_iso_chg");
858  tag.ReplaceAll("mintks_mini_ch,tks_r05_ch","rel_05_mini_iso_chg");
859  tag.ReplaceAll("tks_mini_ch","rel_untruncated_mini_iso_chg");
860 
861 
862  tag.ReplaceAll("el_tks_mt", "Track_mT"); tag.ReplaceAll("mu_tks_mt", "Track_mT"); tag.ReplaceAll("had_tks_mt", "Track_mT");
863  tag.ReplaceAll("el_tks_pt", "Track_pT"); tag.ReplaceAll("mu_tks_pt", "Track_pT"); tag.ReplaceAll("had_tks_pt", "Track_pT");
864  tag.ReplaceAll("el_tks_miniso", "Track_miniso"); tag.ReplaceAll("mu_tks_miniso", "Track_miniso"); tag.ReplaceAll("had_tks_miniso", "Track_miniso");
865  tag.ReplaceAll("el_tks_chg_miniso", "Track_chg_miniso"); tag.ReplaceAll("mu_tks_chg_miniso", "Track_chg_miniso"); tag.ReplaceAll("had_tks_chg_miniso", "Track_chg_miniso");
866 
867 
868 }
869 
870 TString format_tag(TString tag){
871 
872  tag.ReplaceAll(" ","");
873  tag.ReplaceAll(".","");tag.ReplaceAll(",","");
874  tag.ReplaceAll("(",""); tag.ReplaceAll("$",""); tag.ReplaceAll(")","");
875  tag.ReplaceAll("[",""); tag.ReplaceAll("]",""); tag.ReplaceAll("||","_");
876  tag.ReplaceAll("/","_"); tag.ReplaceAll("*",""); tag.ReplaceAll("&&","_");
877  tag.ReplaceAll(">=","ge"); tag.ReplaceAll("<=","se");
878  tag.ReplaceAll(">","g"); tag.ReplaceAll("<","s"); tag.ReplaceAll("=","");
879  tag.ReplaceAll("+",""); tag.ReplaceAll("&","");
880  tag.ReplaceAll("!","not");
881  tag.ReplaceAll("#",""); tag.ReplaceAll("{",""); tag.ReplaceAll("}","");
882 
883  return tag;
884 }
885 
886 sfeats::sfeats(vector<TString> ifile, TString ilabel, int icolor, int istyle, TString icut,
887  TString isamVariable){
888  file = ifile; label = ilabel; cut = icut;
889  color = icolor; style = istyle;
890  isSig = ifile[0].Contains("T1tttt");
891  samVariable = isamVariable;
892  factor = "1";
893  tag = label;
894  tag.ReplaceAll("(",""); tag.ReplaceAll(",","_"); tag.ReplaceAll(")","");
895  tag.ReplaceAll("{",""); tag.ReplaceAll("#,",""); tag.ReplaceAll("}","");
896  doStack = false; isData = false; mcerr=false; doBand = false;
897 }
898 
899 sysfeats::sysfeats(TString iname, TString ititle):
900  name(iname),
901  title(ititle){
902  bincuts = vector<TString>();
903  weights = vector<double>();
904  }
905 void sysfeats::push_back(TString ibincut, double iweight){
906  bincuts.push_back(ibincut);
907  weights.push_back(iweight);
908 }
909 TString sysfeats::bincut(unsigned i){
910  if (i<bincuts.size()) return bincuts[i];
911  else {cout<<"ERROR: bincut out of range"<<endl; return "";}
912 }
913 double sysfeats::weight(unsigned i){
914  if (i<weights.size()) return weights[i];
915  else {cout<<"ERROR: weight out of range"<<endl; return -1.;}
916 }
917 unsigned sysfeats::size(){
918  return weights.size();
919 }
920 
921 // Function that calculates the chi2 of a histogram with respect to the flat hypothesis
922 void calc_chi2(TH1D *histo, float &chi2, int &ndof, float &pvalue, float &average){
923  vector<double> vals[2];
924  double sumx_sig2(0), sum_sig2(0);
925  ndof = 0;
926  for(int bin(1); bin<=histo->GetNbinsX(); bin++){
927  if(histo->GetBinError(bin) > 0){
928  vals[0].push_back(histo->GetBinContent(bin));
929  vals[1].push_back(histo->GetBinError(bin));
930 
931  sumx_sig2 += vals[0][ndof]/pow(vals[1][ndof],2);
932  sum_sig2 += 1/pow(vals[1][ndof],2);
933  ndof++;
934  }
935  }
936  if(sum_sig2<=0){cout<<"All errors in histo are zero. Exiting."<<endl; return;}
937  average = sumx_sig2/sum_sig2;
938  chi2 = 0; ndof--;
939  for(int ival(0); ival <= ndof; ival++){
940  chi2 += pow((vals[0][ival]-average)/vals[1][ival],2);
941  }
942  pvalue = TMath::Prob(chi2,ndof);
943 }
944 
945 // Function that calculates the chi2 from the difference of 2 histos, after normalizing their areas
946 void calc_chi2_diff(TH1D *histo1, TH1D *histo2, float &chi2, int &ndof, float &pvalue, float *average){
947  TH1D *histos[] = {histo1, histo2};
948  vector<double> vals[2][2];
949  double sumx_sig2[] = {0,0}, sum_sig2[] = {0,0};
950  int ndofs[] = {0,0};
951  for(int his(0); his<2; his++){
952  for(int bin(1); bin<=histos[his]->GetNbinsX(); bin++){
953  if(histos[his]->GetBinError(bin) > 0){
954  vals[his][0].push_back(histos[his]->GetBinContent(bin));
955  vals[his][1].push_back(histos[his]->GetBinError(bin));
956 
957  sumx_sig2[his] += vals[his][0][ndofs[his]];
958  sum_sig2[his] += 1;
959  ndofs[his]++;
960  }
961  }
962  if(sum_sig2[his]<=0){cout<<"All errors in histo are zero. Exiting."<<endl; return;}
963  average[his] = sumx_sig2[his]/sum_sig2[his];
964  ndofs[his]--;
965  } // Loop over histos
966 
967  // In principle, we should use just bins where both histos have entries. To be modified
968  if(ndofs[0] != ndofs[1]) {cout<<"First histo has "<<ndofs[0]<<" ndof and second "<<ndofs[1]<<endl; return;}
969  else ndof = ndofs[0];
970  chi2 = 0;
971  double Raver = average[0]/average[1];
972  for(int ival(0); ival <= ndof; ival++){
973  double error(sqrt(pow(vals[0][1][ival],2)+pow(vals[1][1][ival]*Raver,2)));
974  chi2 += pow((vals[0][0][ival]-vals[1][0][ival]*Raver)/error,2);
975  }
976  pvalue = TMath::Prob(chi2,ndof);
977 }
978 
979 long getYieldErr(TChain& tree, TString cut, double& yield, double& uncertainty){
980  const TString hist_name("temp");
981  TH1D temp(hist_name, "", 1, -1.0, 1.0);
982  temp.Sumw2();
983  long entries = tree.Project(hist_name, "0.0", cut);
984  yield = temp.IntegralAndError(0,2,uncertainty);
985  return entries;
986 }
987 
988 void dump_event(small_tree_full &tree, int entry){
989 
990  tree.GetEntry(entry);
991 
992  cout<<Form("event num: %i",tree.event())<<endl;
993  cout<<Form("ntruleps: %i, ntrumus: %i, ntruels: %i, ntrutaush: %i, ntrutausl: %i",tree.ntruleps(),tree.ntrumus(),tree.ntruels(),tree.ntrutaush(),tree.ntrutausl())<<endl;
994  cout<<"print MC doc: "<<endl;
995  for(unsigned int igen = 0; igen<tree.mc_pt().size();igen++){
996  cout<<Form("%i: ID= %i \tpT=%.1f \teta=%.1f \tphi=%.1f \tmom= %i",igen,tree.mc_id().at(igen),tree.mc_pt().at(igen),tree.mc_eta().at(igen),tree.mc_phi().at(igen),static_cast<int>(tree.mc_mom().at(igen)))<<endl;
997  }
998 
999  cout<<"Dumping Tracks"<<endl;
1000  for(unsigned int itks = 0; itks<tree.tks_pt().size();itks++){
1001  cout<<Form("%i: ID= %i \tpT=%.1f \teta=%.1f \tphi=%.1f \tisPrimary= %i \tfrom W= %i \ttruID = %i",itks,tree.tks_id().at(itks),tree.tks_pt().at(itks),tree.tks_eta().at(itks),tree.tks_phi().at(itks),static_cast<int>(tree.tks_is_primary().at(itks)),static_cast<int>(tree.tks_from_w().at(itks)),tree.tks_tru_id().at(itks))<<endl;
1002  }
1003 }
1004 
1005 namespace ra4 {
1006  TColor ucsb_blue(2000, 1/255.,57/255.,166/255.);
1007  TColor ucsb_gold(2001, 255/255.,200/255.,47/255);
1008  TColor penn_red(2002, 149/255.,0/255.,26/255.);
1009  TColor uf_orange(2003, 255/255.,74/255.,0/255.);
1010  TColor uo_green(2004, 0/255.,79/255.,39/255.);
1011  TColor tcu_purple(2005, 52/255.,42/255.,123/255.);
1012  TColor tar_heel_blue(2006, 86/255.,160/255.,211/255.);
1013  TColor sig_teal(2007, 96/255.,159/255.,128/255.);
1014  TColor sig_gold(2008, 215/255.,162/255.,50/255.);
1015  TColor seal_brown(2010, 89/255.,38/255.,11/255.);
1016 }
1017 
1018 namespace dps{
1019  TColor light_blue(2011, 153/255.,220/255.,255/255.);
1020  TColor med_blue(2012, 1/255.,148/255.,218/255.);
1021  TColor red(2015, 250/255.,96/255.,1/255.);
1022  TColor skype_green(2018,9/255.,186/255.,1/255.);
1023  // TColor purple(2019, 172/255.,46/255.,135/255.);
1024  TColor purple(2019, 183/255.,66/255.,176/255.);
1025  TColor ucsb_gold(2020, 255/255.,200/255.,47/255);
1026 
1027 }
1028 
1029 double intGaus(double mean, double sigma, double minX, double maxX){
1030  return (TMath::Erf((maxX-mean)/sigma/sqrt(2.))-TMath::Erf((minX-mean)/sigma/sqrt(2.)))/2.;
1031 }
1032 
1033 
1034 // Code from http://www.hongliangjie.com/2012/12/19/how-to-generate-gamma-random-variables/
1035 // Parameter b could be theta...
1036 double gsl_ran_gamma(const double a, const double b, TRandom3 &rand){
1037  if (a < 1){
1038  double u = rand.Uniform(1);
1039  return gsl_ran_gamma(1.0 + a, b, rand) * pow (u, 1.0 / a);
1040  }
1041 
1042  double x, v, u;
1043  double d = a - 1.0 / 3.0;
1044  double c = (1.0 / 3.0) / sqrt (d);
1045 
1046  while (1) {
1047  do {
1048  x = rand.Gaus(0, 1.0);
1049  v = 1.0 + c * x;
1050  }
1051  while (v <= 0);
1052 
1053  v = v * v * v;
1054  u = rand.Uniform(1);
1055 
1056  if (u < 1 - 0.0331 * x * x * x * x)
1057  break;
1058 
1059  if (log (u) < 0.5 * x * x + d * (1 - v + log (v)))
1060  break;
1061  }
1062 
1063  return b * d * v;
1064 }
1065 
1066 
1067 // yields[Nobs][Nsam] has the entries for each sample for each observable going into kappa
1068 // weights[Nobs][Nsam] has the average weight of each observable for each sample
1069 // powers[Nobs] defines kappa = Product_obs{ Sum_sam{yields[sam][obs]*weights[sam][obs]}^powers[obs] }
1070 double calcKappa(vector<vector<float> > &entries, vector<vector<float> > &weights,
1071  vector<float> &powers, float &mSigma, float &pSigma, bool do_data,
1072  bool verbose, bool do_plot, int nrep){
1073  TRandom3 rand(1234);
1074  styles style("RA4"); style.setDefaultStyle();
1075  int nbadk(0);
1076  TCanvas can;
1077  vector<float> fKappas;
1078  double mean(0.), bignum(1e10);
1079  // Doing kappa variations
1080  for(int rep(0), irep(0); rep < nrep; rep++) {
1081  fKappas.push_back(1.);
1082  bool Denom_is0(false);
1083  for(unsigned obs(0); obs < powers.size(); obs++) {
1084  float observed(0.);
1085  for(unsigned sam(0); sam < entries[obs].size(); sam++) {
1086  // With a flat prior, the expected average of the Poisson with N observed is Gamma(N+1,1)
1087  // Rounding the expected yield for data stats
1088  if(do_data) observed += entries[obs][sam]*weights[obs][sam];
1089  else observed += gsl_ran_gamma(entries[obs][sam]+1,1,rand)*weights[obs][sam];
1090  } // Loop over samples
1091  //if(do_data) observed = gsl_ran_gamma(static_cast<int>(0.5+observed)+1,1,rand);
1092  if(do_data) observed = gsl_ran_gamma(observed+1,1,rand);
1093  if(observed <= 0 && powers[obs] < 0) Denom_is0 = true;
1094  else fKappas[irep] *= pow(observed, powers[obs]);
1095  } // Loop over number of observables going into kappa
1096  if(Denom_is0 && fKappas[irep]==0) {
1097  fKappas.pop_back();
1098  nbadk++;
1099  }else {
1100  if(Denom_is0) fKappas[irep] = bignum;
1101  else mean += fKappas[irep];
1102  irep++;
1103  }
1104  } // Loop over fluctuations of kappa (repetitions)
1105  int ntot(nrep-nbadk);
1106  mean /= static_cast<double>(ntot);
1107 
1108  sort(fKappas.begin(), fKappas.end());
1109  double gSigma = intGaus(0,1,0,1);
1110  int iMedian((nrep-nbadk+1)/2-1);
1111  int imSigma(iMedian-static_cast<int>(gSigma*ntot)), ipSigma(iMedian+static_cast<int>(gSigma*ntot));
1112  float median(fKappas[iMedian]);
1113  mSigma = median-fKappas[imSigma]; pSigma = fKappas[ipSigma]-median;
1114 
1115  // Finding standard value
1116  float stdval(1.);
1117  bool infStd(false);
1118  for(unsigned obs(0); obs < powers.size(); obs++) {
1119  float stdyield(0.);
1120  if(verbose) cout<<obs<<": ";
1121  for(unsigned sam(0); sam < entries[obs].size(); sam++) {
1122  if(verbose) cout<<"Yield"<<sam<<" "<<entries[obs][sam]*weights[obs][sam]
1123  <<", N"<<sam<<" "<<entries[obs][sam]
1124  <<", avW"<<sam<<" "<<weights[obs][sam]<<". ";
1125  stdyield += entries[obs][sam]*weights[obs][sam];
1126  }
1127  if(verbose) cout<<" ==> Total yield "<<stdyield<<endl;
1128  if(stdyield <= 0 && powers[obs] < 0) infStd = true;
1129  else stdval *= pow(stdyield, powers[obs]);
1130  } // Loop over number of observables going into kappa
1131  if(infStd) stdval = median;
1132  else {
1133  int istd(0);
1134  for(int rep(0); rep < ntot; rep++)
1135  if(fKappas[rep]>stdval) {istd = rep; break;}
1136  imSigma = istd-static_cast<int>(gSigma*ntot);
1137  ipSigma = istd+static_cast<int>(gSigma*ntot);
1138  if(imSigma<0){ // Adjusting the length of the interval in case imSigma has less than 1sigma
1139  ipSigma += (-imSigma);
1140  imSigma = 0;
1141  }
1142  if(ipSigma>=ntot){ // Adjusting the length of the interval in case ipSigma has less than 1sigma
1143  imSigma -= (ipSigma-ntot+1);
1144  ipSigma = ntot-1;
1145  }
1146  mSigma = stdval-fKappas[imSigma]; pSigma = fKappas[ipSigma]-stdval;
1147  }
1148 
1149  int nbins(100);
1150  double minH(stdval-3*mSigma), maxH(stdval+3*pSigma);
1151  if(minH < fKappas[0]) minH = fKappas[0];
1152  if(maxH > fKappas[ntot-1]) maxH = fKappas[ntot-1];
1153  TH1D histo("h","",nbins, minH, maxH);
1154  for(int rep(0); rep < ntot; rep++)
1155  histo.Fill(fKappas[rep]);
1156  //histo.SetBinContent(1, histo.GetBinContent(1)+nbadk);
1157  //histo.SetBinContent(nbins, histo.GetBinContent(nbins)+histo.GetBinContent(nbins+1));
1158  histo.Scale(1/histo.Integral());
1159  histo.SetMaximum(histo.GetMaximum()*1.2);
1160  histo.SetLineWidth(3);
1161  histo.Draw();
1162  histo.SetXTitle("Expected value");
1163  histo.SetYTitle("Probability");
1164  histo.Draw();
1165  if(do_plot) can.SaveAs("test.eps");
1166 
1167  double mode(histo.GetBinLowEdge(histo.GetMaximumBin()));
1168  if(verbose) cout<<"Std kappa = "<<stdval<<"+"<<pSigma<<"-"<<mSigma<<". Mean = "<<mean
1169  <<". Mode = "<<mode<<". Median = "<<median<<endl;
1170 
1171  return stdval;
1172 }
1173 
1174 float Efficiency(float num, float den, float &errup, float &errdown){
1175  if(den<=0){cout<<"Denominator is "<<den<<". Exiting"<<endl; return -1.;}
1176 
1177  TH1D hnum("hnum","",1,0,1);
1178  hnum.SetBinContent(1,num);
1179  TH1D hden("hden","",1,0,1);
1180  hden.SetBinContent(1,den);
1181 
1182  TEfficiency heff(hnum, hden);
1183 
1184  errup = heff.GetEfficiencyErrorUp(1);
1185  errdown = heff.GetEfficiencyErrorLow(1);
1186  return num/den;
1187 }
1188 
TColor med_blue(2012, 1/255., 148/255., 218/255.)
std::vector< double > weights
TString cut
virtual int const & ntruleps() const
TString invertcut(TString cut)
TString titlex
TColor skype_green(2018, 9/255., 186/255., 1/255.)
float maxYaxis
void calc_chi2_diff(TH1D *histo1, TH1D *histo2, float &chi2, int &ndof, float &pvalue, float *average)
TColor tcu_purple(2005, 52/255., 42/255., 123/255.)
std::vector< double > nevents
double weight(unsigned i)
long getYieldErr(TChain &tree, TString cut, double &yield, double &uncertainty)
TString title
void format_tag()
TString tagname
virtual std::vector< size_t > const & mc_mom() const
void setDefaultStyle()
Definition: styles.cpp:36
TColor uf_orange(2003, 255/255., 74/255., 0/255.)
virtual std::vector< int > const & tks_tru_id() const
float LabelSize
Definition: styles.hpp:35
virtual std::vector< bool > const & tks_is_primary() const
virtual int const & ntrutausl() const
TColor tar_heel_blue(2006, 86/255., 160/255., 211/255.)
TString tagname
float PadTopMargin
Definition: styles.hpp:36
STL namespace.
float * binning
sfeats(std::vector< TString > ifile, TString ilabel, int icolor=1, int istyle=1, TString icut="1", TString samVariable="noPlot")
void moveYAxisLabel(TH1 *h, float maxi, bool isLog=false)
Definition: styles.cpp:96
float moveRLegend
TString unit
double gsl_ran_gamma(const double a, const double b, TRandom3 &rand)
TColor ucsb_gold(2020, 255/255., 200/255., 47/255)
virtual std::vector< float > const & tks_pt() const
TString whichPlots
TString bincut(unsigned i)
int const & event() const
Definition: small_tree.cpp:517
float LegendSize
Definition: styles.hpp:35
hfeats(TString ivarname, int inbins, float iminx, float imaxx, std::vector< int > isamples, TString ititle="", TString icuts="1", float icut=-1, TString itagname="", bool iskiplog=false, std::vector< double > inevents=std::vector< double >(1,-1.))
TColor ucsb_blue(2000, 1/255., 57/255., 166/255.)
virtual std::vector< float > const & tks_eta() const
bool PU_reweight
TColor light_blue(2011, 153/255., 220/255., 255/255.)
TString luminosity
float Efficiency(float num, float den, float &errup, float &errdown)
std::vector< int > samples
double calcKappa(vector< vector< float > > &entries, vector< vector< float > > &weights, vector< float > &powers, float &mSigma, float &pSigma, bool do_data, bool verbose, bool do_plot, int nrep)
TString cuts
bool addOverflow
float TitleSize
Definition: styles.hpp:35
void dump_event(small_tree_full &tree, int entry)
double intGaus(double mean, double sigma, double minX, double maxX)
TString varname
float xTitleOffset
Definition: styles.hpp:35
std::vector< int > samples
TString cuts2title(TString title)
int nDivisions
Definition: styles.hpp:33
float yTitleOffset
Definition: styles.hpp:35
TString RoundNumber(double num, int decimals, double denom=1.)
Definition: utilities.cpp:191
TColor sig_gold(2008, 215/255., 162/255., 50/255.)
TString varnamex
virtual std::vector< int > const & mc_id() const
void setTitles(TH1 *h, TString xTitle="", TString yTitle="", TString Left="", TString Right="")
Definition: styles.cpp:173
std::vector< TString > bincuts
int nFont
Definition: styles.hpp:33
virtual std::vector< float > const & mc_pt() const
TString tag
tuple file
Definition: parse_card.py:238
float PadRightMargin
Definition: styles.hpp:36
TColor red(2015, 250/255., 96/255., 1/255.)
virtual std::vector< float > const & mc_phi() const
void plot_distributions(vector< sfeats > Samples, vector< hfeats > vars, TString luminosity, TString filetype, TString namestyle, TString dir, bool doRatio, bool showcuts)
virtual int const & ntrutaush() const
void calc_chi2(TH1D *histo, float &chi2, int &ndof, float &pvalue, float &average)
TColor uo_green(2004, 0/255., 79/255., 39/255.)
virtual std::vector< bool > const & tks_from_w() const
TColor penn_red(2002, 149/255., 0/255., 26/255.)
TColor purple(2019, 183/255., 66/255., 176/255.)
void push_back(TString bincut, double weight)
float PadLeftMargin
Definition: styles.hpp:36
pfeats(const std::vector< int > &isamples, const TString &icut="1", const TString &itagname="")
virtual int const & ntrumus() const
virtual std::vector< int > const & tks_id() const
TString varnamey
virtual void GetEntry(const long entry)
virtual std::vector< float > const & tks_phi() const
TColor seal_brown(2010, 89/255., 38/255., 11/255.)
TString titley
void plot_2D_distributions(vector< sfeats > Samples, vector< hfeats > vars, TString luminosity, TString filetype, TString namestyle, TString dir)
unsigned size()
float maxRatio
virtual std::vector< float > const & mc_eta() const
TColor sig_teal(2007, 96/255., 159/255., 128/255.)
float PadBottomMargin
Definition: styles.hpp:36
sysfeats(TString iname, TString ititle)
virtual int const & ntruels() const