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