ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitHzz4l/Efficiency/src/plotEff.cc
Revision: 1.1
Committed: Tue Jun 12 21:31:44 2012 UTC (12 years, 11 months ago) by dkralph
Content type: text/plain
Branch: MAIN
CVS Tags: compiled, HEAD
Log Message:
First commit: A tag and probe selector for id, iso, or trigger efficiencies and a port of Kevin's fitting code.

File Contents

# User Rev Content
1 dkralph 1.1 //================================================================================================
2     //
3     // Signal Extraction
4     //-------------------
5     // 0: probe counting
6     // 1: Breit-Wigner convolved with Crystal Ball function
7     // 2: MC template convolved with Gaussian
8     // 3: Phil's Crystal Ball based "Voigtian" shape
9     // 4: Unbinned MC data convolved with Gaussian
10     //
11     // Background Model
12     //------------------
13     // 0: no background
14     // 1: exponential model
15     // 2: erfc*exp model
16     // 3: double exponential model
17     // 4: linear*exp model
18     // 5: quadratic*exp model
19     //
20     //________________________________________________________________________________________________
21    
22     #include <TROOT.h> // access to gROOT, entry point to ROOT system
23     #include <TSystem.h> // interface to OS
24     #include <TStyle.h> // class to handle ROOT plotting style
25     #include <TFile.h> // file handle class
26     #include <TTree.h> // class to access ntuples
27     #include <TCanvas.h> // class for drawing
28     #include <TH1D.h> // 1D histograms
29     #include <TH2D.h> // 2D histograms
30     #include <TBenchmark.h> // class to track macro running statistics
31     #include <TLorentzVector.h> // class for 4-vector calculations
32     #include <TEfficiency.h> // class to handle efficiency calculations
33     #include <vector> // STL vector class
34     #include <iostream> // standard I/O
35     #include <iomanip> // functions to format standard I/O
36     #include <fstream> // functions for file I/O
37     #include <string> // C++ string class
38     #include <sstream> // class for parsing strings
39    
40     #include "CPlot.h" // helper class for plots
41     #include "MitStyleRemix.h" // style settings for drawing
42     #include "CEffUser1D.h" // class for handling efficiency graphs
43     #include "CEffUser2D.h" // class for handling efficiency tables
44    
45     // structure for output ntuple
46     #include "EffData.h"
47    
48     #include "ZSignals.h"
49     #include "ZBackgrounds.h"
50    
51     // RooFit headers
52     #include "RooRealVar.h"
53     #include "RooCategory.h"
54     #include "RooDataSet.h"
55     #include "RooDataHist.h"
56     #include "RooFormulaVar.h"
57     #include "RooSimultaneous.h"
58     #include "RooAddPdf.h"
59     #include "RooFitResult.h"
60     #include "RooExtendPdf.h"
61    
62     #include "FitArgs.h"
63    
64     // bin size constants
65     #define BIN_SIZE_PASS 2
66     #define BIN_SIZE_FAIL 2
67    
68     TString sOutDir;
69    
70     //=== FUNCTION DECLARATIONS ======================================================================================
71    
72     // generate web page
73     void makeHTML(const TString outDir);
74     void makeHTML(const TString outDir, const TString name, const Int_t n);
75    
76     // Make efficiency graph
77     TGraphAsymmErrors* makeEffGraph(const vector<Double_t> &edgesv, const vector<TTree*> &passv, const vector<TTree*> &failv, const Int_t method,
78     const TString name, const Double_t massLo, const Double_t massHi,
79     const TString format, const Bool_t doAbsEta);
80     TGraphAsymmErrors* makeEffGraph(const vector<Double_t> &edgesv, const vector<TTree*> &passv, const vector<TTree*> &failv,
81     const Int_t sigpass, const Int_t bkgpass, const Int_t sigfail, const Int_t bkgfail,
82     const TString name, const Double_t massLo, const Double_t massHi, const Double_t fitMassLo, const Double_t fitMassHi,
83     const TString format, const Bool_t doAbsEta);
84    
85     // Make 2D efficiency map
86     void makeEffHist2D(TH2D *hEff, TH2D *hErrl, TH2D *hErrh, const vector<TTree*> &passv, const vector<TTree*> &failv, const Int_t method,
87     const TString name, const Double_t massLo, const Double_t massHi,
88     const TString format, const Bool_t doAbsEta);
89     void makeEffHist2D(TH2D *hEff, TH2D *hErrl, TH2D *hErrh, const vector<TTree*> &passv, const vector<TTree*> &failv,
90     const Int_t sigpass, const Int_t bkgpass, const Int_t sigfail, const Int_t bkgfail,
91     const TString name, const Double_t massLo, const Double_t massHi, const Double_t fitMassLo, const Double_t fitMassHi,
92     const TString format, const Bool_t doAbsEta);
93    
94    
95     // Generate MC-based signal templates
96     void generateHistTemplates(const TString infilename,
97     const vector<Double_t> &ptEdgesv, const vector<Double_t> &etaEdgesv, const vector<Double_t> &phiEdgesv, const vector<Double_t> &npvEdgesv,
98     const Double_t fitMassLo, const Double_t fitMassHi, const Bool_t doAbsEta, const Int_t charge, const TH1D* puWeights);
99     void generateDataTemplates(const TString infilename,
100     const vector<Double_t> &ptEdgesv, const vector<Double_t> &etaEdgesv, const vector<Double_t> &phiEdgesv, const vector<Double_t> &npvEdgesv,
101     const Double_t fitMassLo, const Double_t fitMassHi, const Bool_t doAbsEta, const Int_t charge);
102    
103     // Perform count
104     void performCount(Double_t &resEff, Double_t &resErrl, Double_t &resErrh,
105     const Int_t ibin, const Double_t xbinLo, const Double_t xbinHi, const Double_t ybinLo, const Double_t ybinHi,
106     TTree *passTree, TTree *failTree, const Int_t method,
107     const TString name, const Double_t massLo, const Double_t massHi, const TString format, const Bool_t doAbsEta,
108     TCanvas *cpass, TCanvas *cfail);
109    
110     // Perform fit
111     void performFit(Double_t &resEff, Double_t &resErrl, Double_t &resErrh,
112     const Int_t ibin, const Double_t xbinLo, const Double_t xbinHi, const Double_t ybinLo, const Double_t ybinHi,
113     TTree *passTree, TTree *failTree,
114     const Int_t sigpass, const Int_t bkgpass, const Int_t sigfail, const Int_t bkgfail,
115     const TString name, const Double_t massLo, const Double_t massHi, const Double_t fitMassLo, const Double_t fitMassHi,
116     const TString format, const Bool_t doAbsEta, TCanvas *cpass, TCanvas *cfail);
117    
118     // Print correlations
119     void printCorrelations(ostream& os, RooFitResult *res);
120    
121     // Parse fit results file
122     void parseFitResults(ifstream &ifs, double &eff, double &errl, double &errh);
123    
124    
125     //=== MAIN =================================================================================================
126     int main(int argc, char** argv)
127     {
128     FitFlags ctrl;
129     parse_fitargs( argc, argv, ctrl );
130     ctrl.dump();
131    
132     const TString conf = ctrl.conf; // input binning file
133     const Int_t sigModPass = ctrl.sigModPass; // signal extraction method for PASS sample
134     const Int_t bkgModPass = ctrl.bkgModPass; // background model for PASS sample
135     const Int_t sigModFail = ctrl.sigModFail; // signal extraction method for FAIL sample
136     const Int_t bkgModFail = ctrl.bkgModFail; // background model for FAIL sample
137     const TString infilename = ctrl.infilename; // ROOT file of probes
138     const TString outputDir = ctrl.outputDir; // output directory
139     const TString format = ctrl.format; // plot format
140     const Bool_t doAbsEta = ctrl.doAbsEta; // bin in |eta| instead of eta?
141     const Int_t doPU = ctrl.doPU; // PU re-weighting mode
142     const Int_t charge = ctrl.charge; // 0 (no charge requirement), -1, +1
143     const TString mcfilename = ctrl.mcfilename; // ROOT file containing MC events to generate templates from
144     const UInt_t runNumLo = ctrl.runNumLo; // lower bound of run range
145     const UInt_t runNumHi = ctrl.runNumHi; // upper bound of run range
146    
147     //--------------------------------------------------------------------------------------------------------------
148     // Settings
149     //==============================================================================================================
150    
151     // signal extraction mass region
152     const Double_t massLo = 60;
153     const Double_t massHi = 120;
154    
155     // fit mass region
156     const Double_t fitMassLo = massLo;
157     const Double_t fitMassHi = massHi;
158    
159     // Weights for PU-reweighting
160     // TString datapath("/data/blue/ksung");
161     TString datapath("/temp/dkralph/ksung");
162     const TString pufnameA (datapath+"/TagAndProbeExample/PileupReweighting.Summer11DYmm_To_Run2011A.root");
163     const TString pufnameB (datapath+"/TagAndProbeExample/PileupReweighting.Summer11DYmm_To_Run2011B.root");
164     const TString pufnameFull(datapath+"/TagAndProbeExample/PileupReweighting.Summer11DYmm_To_Full2011.root");
165    
166     // efficiency error calculation method
167     // method: 0 -> Clopper-Pearson
168     // 1 -> Feldman-Cousins
169     const Int_t method=0;
170    
171     // y-axis range
172     const Double_t yhigh = 1.03;
173     const Double_t ylow = 0.6;
174    
175     // bin edges for kinematic variables
176     vector<Double_t> ptBinEdgesv;
177     vector<Double_t> etaBinEdgesv;
178     vector<Double_t> phiBinEdgesv;
179     vector<Double_t> npvBinEdgesv;
180    
181     //
182     // parse binning file
183     //
184     ifstream ifs;
185     ifs.open(conf.Data());
186     assert(ifs.is_open());
187     string line;
188     Int_t state=0;
189     Int_t opts[6];
190     while(getline(ifs,line)) {
191     if(line[0]=='#') continue;
192     if(line[0]=='%') {
193     state++;
194     continue;
195     }
196    
197     Double_t edge;
198     stringstream ss(line);
199     if(state==0) {
200     ss >> opts[0] >> opts[1] >> opts[2] >> opts[3] >> opts[4] >> opts[5];
201     } else {
202     ss >> edge;
203     if(state==1) { ptBinEdgesv.push_back(edge); }
204     else if(state==2) { etaBinEdgesv.push_back(edge); }
205     else if(state==3) { phiBinEdgesv.push_back(edge); }
206     else if(state==4) { npvBinEdgesv.push_back(edge); }
207     }
208     }
209     ifs.close();
210    
211     gSystem->mkdir(outputDir,kTRUE);
212     TString outdir(outputDir + TString("/plots"));
213     // hack!
214     sOutDir = ctrl.outputDir + TString("/plots");
215    
216     //--------------------------------------------------------------------------------------------------------------
217     // Main analysis code
218     //==============================================================================================================
219    
220     //
221     // Set up binning in kinematic variables
222     //
223     const UInt_t ptNbins = ptBinEdgesv.size()-1;
224     Double_t ptEdges[ptBinEdgesv.size()];
225     for(UInt_t iedge=0; iedge<ptBinEdgesv.size(); iedge++)
226     ptEdges[iedge] = ptBinEdgesv[iedge];
227    
228     const UInt_t etaNbins = etaBinEdgesv.size()-1;
229     Double_t etaEdges[etaBinEdgesv.size()];
230     for(UInt_t iedge=0; iedge<etaBinEdgesv.size(); iedge++)
231     etaEdges[iedge] = etaBinEdgesv[iedge];
232    
233     const UInt_t phiNbins = phiBinEdgesv.size()-1;
234     Double_t phiEdges[phiBinEdgesv.size()];
235     for(UInt_t iedge=0; iedge<phiBinEdgesv.size(); iedge++)
236     phiEdges[iedge] = phiBinEdgesv[iedge];
237    
238     const UInt_t npvNbins = npvBinEdgesv.size()-1;
239     Double_t npvEdges[npvBinEdgesv.size()];
240     for(UInt_t iedge=0; iedge<npvBinEdgesv.size(); iedge++)
241     npvEdges[iedge] = npvBinEdgesv[iedge];
242    
243     char tname[50];
244     Float_t mass,wgt;
245    
246     vector<TTree*> passTreePtv;
247     vector<TTree*> failTreePtv;
248     for(UInt_t ibin=0; ibin<ptNbins; ibin++) {
249     sprintf(tname,"passPt_%i",ibin);
250     passTreePtv.push_back(new TTree(tname,""));
251     passTreePtv[ibin]->Branch("m",&mass,"m/F");
252     passTreePtv[ibin]->Branch("w",&wgt,"w/F");
253     passTreePtv[ibin]->SetDirectory(0);
254     sprintf(tname,"failPt_%i",ibin);
255     failTreePtv.push_back(new TTree(tname,""));
256     failTreePtv[ibin]->Branch("m",&mass,"m/F");
257     failTreePtv[ibin]->Branch("w",&wgt,"w/F");
258     failTreePtv[ibin]->SetDirectory(0);
259     }
260    
261     vector<TTree*> passTreeEtav;
262     vector<TTree*> failTreeEtav;
263     for(UInt_t ibin=0; ibin<etaNbins; ibin++) {
264     sprintf(tname,"passEta_%i",ibin);
265     passTreeEtav.push_back(new TTree(tname,""));
266     passTreeEtav[ibin]->Branch("m",&mass,"m/F");
267     passTreeEtav[ibin]->Branch("w",&wgt,"w/F");
268     passTreeEtav[ibin]->SetDirectory(0);
269     sprintf(tname,"failEta_%i",ibin);
270     failTreeEtav.push_back(new TTree(tname,""));
271     failTreeEtav[ibin]->Branch("m",&mass,"m/F");
272     failTreeEtav[ibin]->Branch("w",&wgt,"w/F");
273     failTreeEtav[ibin]->SetDirectory(0);
274     }
275    
276     vector<TTree*> passTreePhiv;
277     vector<TTree*> failTreePhiv;
278     for(UInt_t ibin=0; ibin<phiNbins; ibin++) {
279     sprintf(tname,"passPhi_%i",ibin);
280     passTreePhiv.push_back(new TTree(tname,""));
281     passTreePhiv[ibin]->Branch("m",&mass,"m/F");
282     passTreePhiv[ibin]->Branch("w",&wgt,"w/F");
283     passTreePhiv[ibin]->SetDirectory(0);
284     sprintf(tname,"failPhi_%i",ibin);
285     failTreePhiv.push_back(new TTree(tname,""));
286     failTreePhiv[ibin]->Branch("m",&mass,"m/F");
287     failTreePhiv[ibin]->Branch("w",&wgt,"w/F");
288     failTreePhiv[ibin]->SetDirectory(0);
289     }
290    
291     vector<TTree*> passTreeEtaPtv;
292     vector<TTree*> failTreeEtaPtv;
293     for(UInt_t ibin=0; ibin<(etaNbins*ptNbins); ibin++) {
294     sprintf(tname,"passEtaPt_%i",ibin);
295     passTreeEtaPtv.push_back(new TTree(tname,""));
296     passTreeEtaPtv[ibin]->Branch("m",&mass,"m/F");
297     passTreeEtaPtv[ibin]->Branch("w",&wgt,"w/F");
298     passTreeEtaPtv[ibin]->SetDirectory(0);
299     sprintf(tname,"failEtaPt_%i",ibin);
300     failTreeEtaPtv.push_back(new TTree(tname,""));
301     failTreeEtaPtv[ibin]->Branch("m",&mass,"m/F");
302     failTreeEtaPtv[ibin]->Branch("w",&wgt,"w/F");
303     failTreeEtaPtv[ibin]->SetDirectory(0);
304     }
305    
306     vector<TTree*> passTreeEtaPhiv;
307     vector<TTree*> failTreeEtaPhiv;
308     for(UInt_t ibin=0; ibin<(etaNbins*phiNbins); ibin++) {
309     sprintf(tname,"passEtaPhi_%i",ibin);
310     passTreeEtaPhiv.push_back(new TTree(tname,""));
311     passTreeEtaPhiv[ibin]->Branch("m",&mass,"m/F");
312     passTreeEtaPhiv[ibin]->Branch("w",&wgt,"w/F");
313     passTreeEtaPhiv[ibin]->SetDirectory(0);
314     sprintf(tname,"failEtaPhi_%i",ibin);
315     failTreeEtaPhiv.push_back(new TTree(tname,""));
316     failTreeEtaPhiv[ibin]->Branch("m",&mass,"m/F");
317     failTreeEtaPhiv[ibin]->Branch("w",&wgt,"w/F");
318     failTreeEtaPhiv[ibin]->SetDirectory(0);
319     }
320    
321     vector<TTree*> passTreeNPVv;
322     vector<TTree*> failTreeNPVv;
323     for(UInt_t ibin=0; ibin<npvNbins; ibin++) {
324     sprintf(tname,"passNPV_%i",ibin);
325     passTreeNPVv.push_back(new TTree(tname,""));
326     passTreeNPVv[ibin]->Branch("m",&mass,"m/F");
327     passTreeNPVv[ibin]->Branch("w",&wgt,"w/F");
328     passTreeNPVv[ibin]->SetDirectory(0);
329     sprintf(tname,"failNPV_%i",ibin);
330     failTreeNPVv.push_back(new TTree(tname,""));
331     failTreeNPVv[ibin]->Branch("m",&mass,"m/F");
332     failTreeNPVv[ibin]->Branch("w",&wgt,"w/F");
333     failTreeNPVv[ibin]->SetDirectory(0);
334     }
335    
336     //
337     // Pile-up reweighting functions
338     //
339     TFile *pufile = 0;
340     TH1D *puWeights = 0;
341     if(abs(doPU)==1) pufile = new TFile(pufnameA);
342     if(abs(doPU)==2) pufile = new TFile(pufnameB);
343     if(abs(doPU)==3) pufile = new TFile(pufnameFull);
344     if(doPU!=0) {
345     assert(pufile);
346     puWeights = (TH1D*)pufile->Get("puWeights");
347     }
348    
349     //
350     // Generate histogram templates from MC if necessary
351     //
352     if(sigModPass==2 || sigModFail==2) {
353     generateHistTemplates(mcfilename,ptBinEdgesv,etaBinEdgesv,phiBinEdgesv,npvBinEdgesv,fitMassLo,fitMassHi,doAbsEta,charge,puWeights);
354     }
355     if(sigModPass==4 || sigModFail==4) {
356     generateDataTemplates(mcfilename,ptBinEdgesv,etaBinEdgesv,phiBinEdgesv,npvBinEdgesv,fitMassLo,fitMassHi,doAbsEta,charge);
357     }
358    
359     //
360     // Read in probes data
361     //
362     TFile *infile = new TFile(infilename);
363     TTree *eventTree = (TTree*)infile->Get("Events");
364     EffData data;
365     eventTree->SetBranchAddress("Events",&data);
366    
367     for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
368     eventTree->GetEntry(ientry);
369    
370     if((data.q)*charge < 0) continue;
371     if(data.mass < fitMassLo) continue;
372     if(data.mass > fitMassHi) continue;
373     if(data.runNum < runNumLo) continue;
374     if(data.runNum > runNumHi) continue;
375    
376     mass = data.mass;
377     wgt = data.weight;
378     if(doPU>0) wgt *= puWeights->GetBinContent(data.npu+1);
379    
380     Int_t ipt=-1;
381     for(UInt_t ibin=0; ibin<ptNbins; ibin++)
382     if((data.pt >= ptBinEdgesv[ibin]) && (data.pt < ptBinEdgesv[ibin+1]))
383     ipt = ibin;
384     if(ipt<0) continue;
385    
386     Int_t ieta=-1;
387     for(UInt_t ibin=0; ibin<etaNbins; ibin++) {
388     if(doAbsEta) {
389     assert(etaBinEdgesv[ibin]>=0);
390     if((fabs(data.eta) >= etaBinEdgesv[ibin]) && (fabs(data.eta) < etaBinEdgesv[ibin+1]))
391     ieta = ibin;
392     } else {
393     if((data.eta >= etaBinEdgesv[ibin]) && (data.eta < etaBinEdgesv[ibin+1]))
394     ieta = ibin;
395     }
396     }
397     if(ieta<0) continue;
398    
399     Int_t iphi=-1;
400     for(UInt_t ibin=0; ibin<phiNbins; ibin++)
401     if((data.phi >= phiBinEdgesv[ibin]) && (data.phi < phiBinEdgesv[ibin+1]))
402     iphi = ibin;
403     if(iphi<0) continue;
404    
405     Int_t inpv=-1;
406     for(UInt_t ibin=0; ibin<npvNbins; ibin++)
407     if((data.npv >= npvBinEdgesv[ibin]) && (data.npv < npvBinEdgesv[ibin+1]))
408     inpv = ibin;
409     // if(inpv<0) continue;
410    
411     if(data.pass) {
412     passTreePtv[ipt]->Fill();
413     passTreeEtav[ieta]->Fill();
414     passTreePhiv[iphi]->Fill();
415     passTreeEtaPtv[ipt*etaNbins + ieta]->Fill();
416     passTreeEtaPhiv[iphi*etaNbins + ieta]->Fill();
417     if(inpv>=0) passTreeNPVv[inpv]->Fill();
418     } else {
419     failTreePtv[ipt]->Fill();
420     failTreeEtav[ieta]->Fill();
421     failTreePhiv[iphi]->Fill();
422     failTreeEtaPtv[ipt*etaNbins + ieta]->Fill();
423     failTreeEtaPhiv[iphi*etaNbins + ieta]->Fill();
424     if(inpv>=0) failTreeNPVv[inpv]->Fill();
425     }
426     }
427     delete infile;
428     infile=0, eventTree=0;
429    
430    
431     //
432     // Compute efficiencies and make plots
433     //
434     TCanvas *c = MakeCanvas("c","c",800,600);
435    
436     TGraphAsymmErrors *grEffPt=0;
437     TGraphAsymmErrors *grEffEta=0;
438     TGraphAsymmErrors *grEffPhi=0;
439     TGraphAsymmErrors *grEffNPV=0;
440     TH2D *hEffEtaPt = new TH2D("hEffEtaPt","",etaNbins,etaEdges,ptNbins,ptEdges);
441     TH2D *hErrlEtaPt = (TH2D*)hEffEtaPt->Clone("hErrlEtaPt");
442     TH2D *hErrhEtaPt = (TH2D*)hEffEtaPt->Clone("hErrhEtaPt");
443     TH2D *hEffEtaPhi = new TH2D("hEffEtaPhi","",etaNbins,etaEdges,phiNbins,phiEdges);
444     TH2D *hErrlEtaPhi = (TH2D*)hEffEtaPhi->Clone("hErrlEtaPhi");
445     TH2D *hErrhEtaPhi = (TH2D*)hEffEtaPhi->Clone("hErrhEtaPhi");
446    
447     if(sigModPass==0 && sigModFail==0) { // probe counting
448    
449     // efficiency in pT
450     if(opts[0]) {
451     grEffPt = makeEffGraph(ptBinEdgesv, passTreePtv, failTreePtv, method, "pt", massLo, massHi, format, doAbsEta);
452     grEffPt->SetName("grEffPt");
453     CPlot plotEffPt("effpt","","probe p_{T} [GeV/c]","#varepsilon",sOutDir);
454     plotEffPt.AddGraph(grEffPt,"",kBlack);
455     plotEffPt.SetYRange(ylow,yhigh);
456     plotEffPt.SetXRange(0.9*(ptBinEdgesv[0]),1.1*(ptBinEdgesv[ptNbins-1]));
457     plotEffPt.Draw(c,kTRUE,format);
458     }
459    
460     // efficiency in eta
461     if(opts[1]) {
462     grEffEta = makeEffGraph(etaBinEdgesv, passTreeEtav, failTreeEtav, method, "eta", massLo, massHi, format, doAbsEta);
463     grEffEta->SetName("grEffEta");
464     CPlot plotEffEta("effeta","","probe #eta","#varepsilon",sOutDir);
465     if(doAbsEta) plotEffEta.SetXTitle("probe |#eta|");
466     plotEffEta.AddGraph(grEffEta,"",kBlack);
467     plotEffEta.SetYRange(0.2,1.04);
468     plotEffEta.Draw(c,kTRUE,format);
469    
470     CPlot plotEffEta2("effeta2","","probe #eta","#varepsilon",sOutDir);
471     if(doAbsEta) plotEffEta2.SetXTitle("probe |#eta|");
472     plotEffEta2.AddGraph(grEffEta,"",kBlack);
473     plotEffEta2.SetYRange(ylow,yhigh);
474     plotEffEta2.Draw(c,kTRUE,format);
475     }
476    
477     // efficiency in phi
478     if(opts[2]) {
479     grEffPhi = makeEffGraph(phiBinEdgesv, passTreePhiv, failTreePhiv, method, "phi", massLo, massHi, format, doAbsEta);
480     grEffPhi->SetName("grEffPhi");
481     CPlot plotEffPhi("effphi","","probe #phi","#varepsilon",sOutDir);
482     plotEffPhi.AddGraph(grEffPhi,"",kBlack);
483     plotEffPhi.SetYRange(ylow,yhigh);
484     plotEffPhi.Draw(c,kTRUE,format);
485     }
486    
487     // efficiency in N_PV
488     if(opts[3]) {
489     grEffNPV = makeEffGraph(npvBinEdgesv, passTreeNPVv, failTreeNPVv, method, "npv", massLo, massHi, format, doAbsEta);
490     grEffNPV->SetName("grEffNPV");
491     CPlot plotEffNPV("effnpv","","N_{PV}","#varepsilon",sOutDir);
492     plotEffNPV.AddGraph(grEffNPV,"",kBlack);
493     plotEffNPV.SetYRange(ylow,yhigh);
494     plotEffNPV.Draw(c,kTRUE,format);
495     }
496    
497     gStyle->SetPalette(1);
498     c->SetRightMargin(0.15);
499     c->SetLeftMargin(0.15);
500    
501     //
502     // eta-pT efficiency maps
503     //
504     if(opts[4]) {
505     makeEffHist2D(hEffEtaPt, hErrlEtaPt, hErrhEtaPt, passTreeEtaPtv, failTreeEtaPtv, method, "etapt", massLo, massHi, format, doAbsEta);
506     hEffEtaPt->SetTitleOffset(1.2,"Y");
507     if(ptNbins>2)
508     hEffEtaPt->GetYaxis()->SetRangeUser(ptBinEdgesv[0],ptBinEdgesv[ptNbins-2]);
509     CPlot plotEffEtaPt("effetapt","","probe #eta","probe p_{T} [GeV/c]",sOutDir);
510     if(doAbsEta) plotEffEtaPt.SetXTitle("probe |#eta|");
511     plotEffEtaPt.AddHist2D(hEffEtaPt,"COLZ");
512     plotEffEtaPt.Draw(c,kTRUE,format);
513    
514     hErrlEtaPt->SetTitleOffset(1.2,"Y");
515     if(ptNbins>2)
516     hErrlEtaPt->GetYaxis()->SetRangeUser(ptBinEdgesv[0],ptBinEdgesv[ptNbins-2]);
517     CPlot plotErrlEtaPt("errletapt","","probe #eta","probe p_{T} [GeV/c]",sOutDir);
518     if(doAbsEta) plotErrlEtaPt.SetXTitle("probe |#eta|");
519     plotErrlEtaPt.AddHist2D(hErrlEtaPt,"COLZ");
520     plotErrlEtaPt.Draw(c,kTRUE,format);
521    
522     hErrhEtaPt->SetTitleOffset(1.2,"Y");
523     if(ptNbins>2)
524     hErrhEtaPt->GetYaxis()->SetRangeUser(ptBinEdgesv[0],ptBinEdgesv[ptNbins-2]);
525     CPlot plotErrhEtaPt("errhetapt","","probe #eta","probe p_{T} [GeV/c]",sOutDir);
526     if(doAbsEta) plotErrhEtaPt.SetXTitle("probe |#eta|");
527     plotErrhEtaPt.AddHist2D(hErrhEtaPt,"COLZ");
528     plotErrhEtaPt.Draw(c,kTRUE,format);
529     }
530    
531     //
532     // eta-phi efficiency maps
533     //
534     if(opts[5]) {
535     makeEffHist2D(hEffEtaPhi, hErrlEtaPhi, hErrhEtaPhi, passTreeEtaPhiv, failTreeEtaPhiv, method, "etaphi", massLo, massHi, format, doAbsEta);
536     hEffEtaPhi->SetTitleOffset(1.2,"Y");
537     CPlot plotEffEtaPhi("effetaphi","","probe #eta","probe #phi",sOutDir);
538     if(doAbsEta) plotEffEtaPhi.SetXTitle("probe |#eta|");
539     plotEffEtaPhi.AddHist2D(hEffEtaPhi,"COLZ");
540     plotEffEtaPhi.Draw(c,kTRUE,format);
541    
542     hErrlEtaPhi->SetTitleOffset(1.2,"Y");
543     CPlot plotErrlEtaPhi("errletaphi","","probe #eta","probe #phi",sOutDir);
544     plotErrlEtaPhi.AddHist2D(hErrlEtaPhi,"COLZ");
545     if(doAbsEta) plotErrlEtaPhi.SetXTitle("probe |#eta|");
546     plotErrlEtaPhi.Draw(c,kTRUE,format);
547    
548     hErrhEtaPhi->SetTitleOffset(1.2,"Y");
549     CPlot plotErrhEtaPhi("errhetaphi","","probe #eta","probe #phi",sOutDir);
550     if(doAbsEta) plotErrhEtaPhi.SetXTitle("probe |#eta|");
551     plotErrhEtaPhi.AddHist2D(hErrhEtaPhi,"COLZ");
552     plotErrhEtaPhi.Draw(c,kTRUE,format);
553     }
554    
555     } else {
556    
557     // efficiency in pT
558     if(opts[0]) {
559     grEffPt = makeEffGraph(ptBinEdgesv, passTreePtv, failTreePtv, sigModPass, bkgModPass, sigModFail, bkgModFail, "pt", massLo, massHi, fitMassLo, fitMassHi, format, doAbsEta);
560     grEffPt->SetName("grEffPt");
561     CPlot plotEffPt("effpt","","probe p_{T} [GeV/c]","#varepsilon",sOutDir);
562     plotEffPt.AddGraph(grEffPt,"",kBlack);
563     plotEffPt.SetYRange(ylow,yhigh);
564     plotEffPt.SetXRange(0.9*(ptBinEdgesv[0]),1.1*(ptBinEdgesv[ptNbins-1]));
565     plotEffPt.Draw(c,kTRUE,format);
566     }
567    
568     // efficiency in eta
569     if(opts[1]) {
570     grEffEta = makeEffGraph(etaBinEdgesv, passTreeEtav, failTreeEtav, sigModPass, bkgModPass, sigModFail, bkgModFail, "eta", massLo, massHi, fitMassLo, fitMassHi, format, doAbsEta);
571     grEffEta->SetName("grEffEta");
572     CPlot plotEffEta("effeta","","probe #eta","#varepsilon",sOutDir);
573     if(doAbsEta) plotEffEta.SetXTitle("probe |#eta|");
574     plotEffEta.AddGraph(grEffEta,"",kBlack);
575     plotEffEta.SetYRange(0.2,1.04);
576     plotEffEta.Draw(c,kTRUE,format);
577    
578     CPlot plotEffEta2("effeta2","","probe #eta","#varepsilon",sOutDir);
579     if(doAbsEta) plotEffEta2.SetXTitle("probe |#eta|");
580     plotEffEta2.AddGraph(grEffEta,"",kBlack);
581     plotEffEta2.SetYRange(ylow,yhigh);
582     plotEffEta2.Draw(c,kTRUE,format);
583     }
584    
585     // efficiency in phi
586     if(opts[2]) {
587     grEffPhi = makeEffGraph(phiBinEdgesv, passTreePhiv, failTreePhiv, sigModPass, bkgModPass, sigModFail, bkgModFail, "phi", massLo, massHi, fitMassLo, fitMassHi, format, doAbsEta);
588     grEffPhi->SetName("grEffPhi");
589     CPlot plotEffPhi("effphi","","probe #phi","#varepsilon",sOutDir);
590     plotEffPhi.AddGraph(grEffPhi,"",kBlack);
591     plotEffPhi.SetYRange(ylow,yhigh);
592     plotEffPhi.Draw(c,kTRUE,format);
593     }
594    
595     // efficiency in N_PV
596     if(opts[3]) {
597     grEffNPV = makeEffGraph(npvBinEdgesv, passTreeNPVv, failTreeNPVv, sigModPass, bkgModPass, sigModFail, bkgModFail, "npv", massLo, massHi, fitMassLo, fitMassHi, format, doAbsEta);
598     grEffNPV->SetName("grEffNPV");
599     CPlot plotEffNPV("effnpv","","N_{PV}","#varepsilon",sOutDir);
600     plotEffNPV.AddGraph(grEffNPV,"",kBlack);
601     plotEffNPV.SetYRange(ylow,yhigh);
602     plotEffNPV.Draw(c,kTRUE,format);
603     }
604    
605    
606     gStyle->SetPalette(1);
607     c->SetRightMargin(0.15);
608     c->SetLeftMargin(0.15);
609    
610     //
611     // eta-pT efficiency maps
612     //
613     if(opts[4]) {
614     makeEffHist2D(hEffEtaPt, hErrlEtaPt, hErrhEtaPt, passTreeEtaPtv, failTreeEtaPtv, sigModPass, bkgModPass, sigModFail, bkgModFail, "etapt", massLo, massHi, fitMassLo, fitMassHi, format, doAbsEta);
615     hEffEtaPt->SetTitleOffset(1.2,"Y");
616     hEffEtaPt->GetYaxis()->SetRangeUser(ptBinEdgesv[0],ptBinEdgesv[ptNbins-2]);
617     CPlot plotEffEtaPt("effetapt","","probe #eta","probe p_{T} [GeV/c]",sOutDir);
618     if(doAbsEta) plotEffEtaPt.SetXTitle("probe |#eta|");
619     plotEffEtaPt.AddHist2D(hEffEtaPt,"COLZ");
620     plotEffEtaPt.Draw(c,kTRUE,format);
621    
622     hErrlEtaPt->SetTitleOffset(1.2,"Y");
623     hErrlEtaPt->GetYaxis()->SetRangeUser(ptBinEdgesv[0],ptBinEdgesv[ptNbins-2]);
624     CPlot plotErrlEtaPt("errletapt","","probe #eta","probe p_{T} [GeV/c]",sOutDir);
625     if(doAbsEta) plotErrlEtaPt.SetXTitle("probe |#eta|");
626     plotErrlEtaPt.AddHist2D(hErrlEtaPt,"COLZ");
627     plotErrlEtaPt.Draw(c,kTRUE,format);
628    
629     hErrhEtaPt->SetTitleOffset(1.2,"Y");
630     hErrhEtaPt->GetYaxis()->SetRangeUser(ptBinEdgesv[0],ptBinEdgesv[ptNbins-2]);
631     CPlot plotErrhEtaPt("errhetapt","","probe #eta","probe p_{T} [GeV/c]",sOutDir);
632     if(doAbsEta) plotErrhEtaPt.SetXTitle("probe |#eta|");
633     plotErrhEtaPt.AddHist2D(hErrhEtaPt,"COLZ");
634     plotErrhEtaPt.Draw(c,kTRUE,format);
635     }
636    
637     //
638     // eta-phi efficiency maps
639     //
640     if(opts[5]) {
641     makeEffHist2D(hEffEtaPhi, hErrlEtaPhi, hErrhEtaPhi, passTreeEtaPhiv, failTreeEtaPhiv, sigModPass, bkgModPass, sigModFail, bkgModFail, "etaphi", massLo, massHi, fitMassLo, fitMassHi, format, doAbsEta);
642     hEffEtaPhi->SetTitleOffset(1.2,"Y");
643     CPlot plotEffEtaPhi("effetaphi","","probe #eta","probe #phi",sOutDir);
644     if(doAbsEta) plotEffEtaPhi.SetXTitle("probe |#eta|");
645     plotEffEtaPhi.AddHist2D(hEffEtaPhi,"COLZ");
646     plotEffEtaPhi.Draw(c,kTRUE,format);
647    
648     hErrlEtaPhi->SetTitleOffset(1.2,"Y");
649     CPlot plotErrlEtaPhi("errletaphi","","probe #eta","probe #phi",sOutDir);
650     plotErrlEtaPhi.AddHist2D(hErrlEtaPhi,"COLZ");
651     if(doAbsEta) plotErrlEtaPhi.SetXTitle("probe |#eta|");
652     plotErrlEtaPhi.Draw(c,kTRUE,format);
653    
654     hErrhEtaPhi->SetTitleOffset(1.2,"Y");
655     CPlot plotErrhEtaPhi("errhetaphi","","probe #eta","probe #phi",sOutDir);
656     if(doAbsEta) plotErrhEtaPhi.SetXTitle("probe |#eta|");
657     plotErrhEtaPhi.AddHist2D(hErrhEtaPhi,"COLZ");
658     plotErrhEtaPhi.Draw(c,kTRUE,format);
659     }
660     }
661    
662     // Undo scaling of axes before saving to file
663     hEffEtaPt->GetYaxis()->SetRangeUser(ptBinEdgesv[0],ptBinEdgesv[ptNbins]);
664     hErrlEtaPt->GetYaxis()->SetRangeUser(ptBinEdgesv[0],ptBinEdgesv[ptNbins]);
665     hErrhEtaPt->GetYaxis()->SetRangeUser(ptBinEdgesv[0],ptBinEdgesv[ptNbins]);
666    
667    
668     //--------------------------------------------------------------------------------------------------------------
669     // Output
670     //==============================================================================================================
671    
672     cout << "*" << endl;
673     cout << "* SUMMARY" << endl;
674     cout << "*--------------------------------------------------" << endl;
675     cout << endl;
676    
677     TFile *outfile = new TFile(outputDir + TString("/eff.root"), "RECREATE");
678     if(grEffPt) grEffPt->Write();
679     if(grEffEta) grEffEta->Write();
680     if(grEffPhi) grEffPhi->Write();
681     if(grEffNPV) grEffNPV->Write();
682     hEffEtaPt->Write();
683     hErrlEtaPt->Write();
684     hErrhEtaPt->Write();
685     hEffEtaPhi->Write();
686     hErrlEtaPhi->Write();
687     hErrhEtaPhi->Write();
688     outfile->Close();
689     delete outfile;
690    
691     makeHTML(outputDir);
692     makeHTML(outputDir, "pt", ptNbins);
693     makeHTML(outputDir, "eta", etaNbins);
694     makeHTML(outputDir, "phi", phiNbins);
695     makeHTML(outputDir, "npv", npvNbins);
696     makeHTML(outputDir, "etapt", etaNbins*ptNbins);
697     makeHTML(outputDir, "etaphi", etaNbins*phiNbins);
698    
699     ofstream txtfile;
700     char txtfname[100];
701     sprintf(txtfname,"%s/summary.txt",outputDir.Data());
702     txtfile.open(txtfname);
703     assert(txtfile.is_open());
704    
705     CEffUser2D effetapt;
706     CEffUser2D effetaphi;
707    
708     CEffUser1D effpt;
709     CEffUser1D effeta;
710     CEffUser1D effphi;
711     CEffUser1D effnpv;
712    
713     if(hEffEtaPt->GetEntries()>0) {
714     effetapt.loadEff(hEffEtaPt,hErrlEtaPt,hErrhEtaPt);
715     effetapt.printEff(txtfile); txtfile << endl;
716     effetapt.printErrLow(txtfile); txtfile << endl;
717     effetapt.printErrHigh(txtfile); txtfile << endl;
718     txtfile << endl;
719     }
720    
721     if(hEffEtaPhi->GetEntries()>0) {
722     effetaphi.loadEff(hEffEtaPhi,hErrlEtaPhi,hErrhEtaPhi);
723     effetaphi.printEff(txtfile); txtfile << endl;
724     effetaphi.printErrLow(txtfile); txtfile << endl;
725     effetaphi.printErrHigh(txtfile); txtfile << endl;
726     txtfile << endl;
727     }
728    
729     if(grEffPt) {
730     effpt.loadEff(grEffPt);
731     effpt.printEff(txtfile);
732     txtfile << endl;
733     effpt.printErrLow(txtfile);
734     txtfile << endl;
735     effpt.printErrHigh(txtfile);
736     txtfile << endl;
737     txtfile << endl;
738     }
739    
740     if(grEffEta) {
741     effeta.loadEff(grEffEta);
742     effeta.printEff(txtfile);
743     txtfile << endl;
744     effeta.printErrLow(txtfile);
745     txtfile << endl;
746     effeta.printErrHigh(txtfile);
747     txtfile << endl;
748     txtfile << endl;
749     }
750    
751     if(grEffPhi) {
752     effphi.loadEff(grEffPhi);
753     effphi.printEff(txtfile);
754     txtfile << endl;
755     effphi.printErrLow(txtfile);
756     txtfile << endl;
757     effphi.printErrHigh(txtfile);
758     txtfile << endl;
759     txtfile << endl;
760     }
761    
762     if(grEffNPV) {
763     effnpv.loadEff(grEffNPV);
764     effnpv.printEff(txtfile);
765     txtfile << endl;
766     effnpv.printErrLow(txtfile);
767     txtfile << endl;
768     effnpv.printErrHigh(txtfile);
769     }
770     txtfile.close();
771    
772     cout << endl;
773     cout << " <> Output saved in " << outputDir << "/" << endl;
774     cout << endl;
775    
776     }
777    
778    
779     //=== FUNCTION DEFINITIONS ======================================================================================
780    
781     //--------------------------------------------------------------------------------------------------
782     void makeHTML(const TString outDir)
783     {
784     ofstream htmlfile;
785     char htmlfname[100];
786     sprintf(htmlfname,"%s/plots.html",outDir.Data());
787     htmlfile.open(htmlfname);
788     htmlfile << "<!DOCTYPE html" << endl;
789     htmlfile << " PUBLIC \"-//W3C//DTD HTML 3.2//EN\">" << endl;
790     htmlfile << "<html>" << endl;
791    
792     htmlfile << "<body bgcolor=\"EEEEEE\">" << endl;
793    
794     htmlfile << "<table border=\"0\" cellspacing=\"5\" width=\"100%\">" << endl;
795     htmlfile << "<tr>" << endl;
796     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"plots/effpt.png\"><img src=\"plots/effpt.png\" alt=\"plots/effpt.png\" width=\"100%\"></a></td>" << endl;
797     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"plots/effeta.png\"><img src=\"plots/effeta.png\" alt=\"plots/effeta.png\" width=\"100%\"></a></td>" << endl;
798     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"plots/effeta2.png\"><img src=\"plots/effeta2.png\" alt=\"plots/effeta2.png\" width=\"100%\"></a></td>" << endl;
799     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"plots/effphi.png\"><img src=\"plots/effphi.png\" alt=\"plots/effphi.png\" width=\"100%\"></a></td>" << endl;
800     htmlfile << "</tr>" << endl;
801     htmlfile << "<tr>" << endl;
802     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"pt.html\">pT bins</a></td>" << endl;
803     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"eta.html\">&eta; bins</a></td>" << endl;
804     htmlfile << "<td width=\"25%\"></td>" << endl;
805     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"phi.html\">&phi; bins</a></td>" << endl;
806     htmlfile << "</tr>" << endl;
807     htmlfile << "<tr>" << endl;
808     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"plots/effetapt.png\"><img src=\"plots/effetapt.png\" alt=\"plots/effetapt.png\" width=\"100%\"></a></td>" << endl;
809     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"plots/errletapt.png\"><img src=\"plots/errletapt.png\" alt=\"plots/errletapt.png\" width=\"100%\"></a></td>" << endl;
810     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"plots/errhetapt.png\"><img src=\"plots/errhetapt.png\" alt=\"plots/errhetapt.png\" width=\"100%\"></a></td>" << endl;
811     htmlfile << "<td width=\"25%\"></td>" << endl;
812     htmlfile << "</tr>" << endl;
813     htmlfile << "<tr>" << endl;
814     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"etapt.html\">&eta;-pT bins</a></td>" << endl;
815     htmlfile << "<td width=\"25%\"></td>" << endl;
816     htmlfile << "<td width=\"25%\"></td>" << endl;
817     htmlfile << "<td width=\"25%\"></td>" << endl;
818     htmlfile << "</tr>" << endl;
819     htmlfile << "<tr>" << endl;
820     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"plots/effetaphi.png\"><img src=\"plots/effetaphi.png\" alt=\"plots/effetaphi.png\" width=\"100%\"></a></td>" << endl;
821     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"plots/errletaphi.png\"><img src=\"plots/errletaphi.png\" alt=\"plots/errletaphi.png\" width=\"100%\"></a></td>" << endl;
822     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"plots/errhetaphi.png\"><img src=\"plots/errhetaphi.png\" alt=\"plots/errhetaphi.png\" width=\"100%\"></a></td>" << endl;
823     htmlfile << "<td width=\"25%\"></td>" << endl;
824     htmlfile << "</tr>" << endl;
825     htmlfile << "<tr>" << endl;
826     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"etaphi.html\">&eta;-&phi; bins</a></td>" << endl;
827     htmlfile << "<td width=\"25%\"></td>" << endl;
828     htmlfile << "<td width=\"25%\"></td>" << endl;
829     htmlfile << "<td width=\"25%\"></td>" << endl;
830     htmlfile << "</tr>" << endl;
831     htmlfile << "<tr>" << endl;
832     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"plots/effnpv.png\"><img src=\"plots/effnpv.png\" alt=\"plots/effnpv.png\" width=\"100%\"></a></td>" << endl;
833     htmlfile << "<td width=\"25%\"></td>" << endl;
834     htmlfile << "<td width=\"25%\"></td>" << endl;
835     htmlfile << "<td width=\"25%\"></td>" << endl;
836     htmlfile << "</tr>" << endl;
837     htmlfile << "<tr>" << endl;
838     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"npv.html\">N_PV bins</a></td>" << endl;
839     htmlfile << "<td width=\"25%\"></td>" << endl;
840     htmlfile << "<td width=\"25%\"></td>" << endl;
841     htmlfile << "<td width=\"25%\"></td>" << endl;
842     htmlfile << "</tr>" << endl;
843     htmlfile << "</table>" << endl;
844     htmlfile << "<hr />" << endl;
845    
846     htmlfile << "</body>" << endl;
847     htmlfile << "</html>" << endl;
848     htmlfile.close();
849     }
850    
851     void makeHTML(const TString outDir, const TString name, const Int_t n)
852     {
853     ofstream htmlfile;
854     char htmlfname[100];
855     sprintf(htmlfname,"%s/%s.html",outDir.Data(),name.Data());
856     htmlfile.open(htmlfname);
857     htmlfile << "<!DOCTYPE html" << endl;
858     htmlfile << " PUBLIC \"-//W3C//DTD HTML 3.2//EN\">" << endl;
859     htmlfile << "<html>" << endl;
860    
861     htmlfile << "<body bgcolor=\"EEEEEE\">" << endl;
862    
863     htmlfile << "<table border=\"0\" cellspacing=\"5\" width=\"100%\">" << endl;
864     Int_t i;
865     for(i=0; i<n; i++) {
866     if(i%2==0) htmlfile << "<tr>" << endl;
867     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"plots/pass" << name << "_" << i << ".png\"><img src=\"plots/pass" << name << "_" << i << ".png\"alt=\"plots/pass" << name << "_" << i << ".png\" width=\"100%\"></a></td>" << endl;
868     htmlfile << "<td width=\"25%\"><a target=\"_blank\" href=\"plots/fail" << name << "_" << i << ".png\"><img src=\"plots/fail" << name << "_" << i << ".png\"alt=\"plots/fail" << name << "_" << i << ".png\" width=\"100%\"></a></td>" << endl;
869     if(i%2) htmlfile << "</tr>" << endl;
870     }
871     if(i%2) {
872     htmlfile << "<td width=\"25%\"></td>" << endl;
873     htmlfile << "<td width=\"25%\"></td>" << endl;
874     htmlfile << "</tr>" << endl;
875     }
876     htmlfile << "</table>" << endl;
877     htmlfile << "<hr />" << endl;
878    
879     htmlfile << "</body>" << endl;
880     htmlfile << "</html>" << endl;
881     htmlfile.close();
882     }
883    
884     //--------------------------------------------------------------------------------------------------
885     TGraphAsymmErrors* makeEffGraph(const vector<Double_t> &edgesv, const vector<TTree*> &passv, const vector<TTree*> &failv, const Int_t method,
886     const TString name, const Double_t massLo, const Double_t massHi, const TString format, const Bool_t doAbsEta)
887     {
888     const UInt_t n = edgesv.size()-1;
889     Double_t xval[n], xerr[n];
890     Double_t yval[n], yerrl[n], yerrh[n];
891    
892     TCanvas *cpass = MakeCanvas("cpass","cpass",720,540);
893     cpass->SetWindowPosition(cpass->GetWindowTopX()+cpass->GetBorderSize()+800,0);
894     TCanvas *cfail = MakeCanvas("cfail","cfail",720,540);
895     cfail->SetWindowPosition(cfail->GetWindowTopX()+cfail->GetBorderSize()+800,cpass->GetWindowTopX()+cfail->GetBorderSize()+540);
896    
897     for(UInt_t ibin=0; ibin<n; ibin++) {
898     xval[ibin] = 0.5*(edgesv[ibin+1] + edgesv[ibin]);
899     xerr[ibin] = 0.5*(edgesv[ibin+1] - edgesv[ibin]);
900    
901     Double_t eff, errl, errh;
902     performCount(eff, errl, errh, ibin, edgesv[ibin], edgesv[ibin+1], 0, 0,
903     passv[ibin], failv[ibin], method,
904     name, massLo, massHi, format, doAbsEta,
905     cpass, cfail);
906    
907     yval[ibin] = eff;
908     yerrl[ibin] = errl;
909     yerrh[ibin] = errh;
910     }
911     delete cpass;
912     delete cfail;
913    
914     return new TGraphAsymmErrors(n,xval,yval,xerr,xerr,yerrl,yerrh);
915     }
916    
917     TGraphAsymmErrors* makeEffGraph(const vector<Double_t> &edgesv, const vector<TTree*> &passv, const vector<TTree*> &failv,
918     const Int_t sigpass, const Int_t bkgpass, const Int_t sigfail, const Int_t bkgfail,
919     const TString name, const Double_t massLo, const Double_t massHi, const Double_t fitMassLo, const Double_t fitMassHi,
920     const TString format, const Bool_t doAbsEta)
921     {
922     const UInt_t n = edgesv.size()-1;
923     Double_t xval[n], xerr[n];
924     Double_t yval[n], yerrl[n], yerrh[n];
925    
926     TCanvas *cpass = MakeCanvas("cpass","cpass",720,540);
927     cpass->SetWindowPosition(cpass->GetWindowTopX()+cpass->GetBorderSize()+800,0);
928     TCanvas *cfail = MakeCanvas("cfail","cfail",720,540);
929     cfail->SetWindowPosition(cfail->GetWindowTopX()+cfail->GetBorderSize()+800,cpass->GetWindowTopX()+cfail->GetBorderSize()+540);
930    
931     for(UInt_t ibin=0; ibin<n; ibin++) {
932     xval[ibin] = 0.5*(edgesv[ibin+1] + edgesv[ibin]);
933     xerr[ibin] = 0.5*(edgesv[ibin+1] - edgesv[ibin]);
934    
935     ifstream rfile;
936     char rname[100];
937     sprintf(rname,"%s/fitres%s_%i.txt",sOutDir.Data(),name.Data(),ibin);
938     rfile.open(rname);
939    
940     Double_t eff, errl, errh;
941     if(rfile.is_open()) {
942     parseFitResults(rfile,eff,errl,errh);
943     rfile.close();
944    
945     } else {
946     performFit(eff, errl, errh, ibin, edgesv[ibin], edgesv[ibin+1], 0, 0,
947     passv[ibin], failv[ibin],
948     sigpass, bkgpass, sigfail, bkgfail,
949     name, massLo, massHi, fitMassLo, fitMassHi,
950     format, doAbsEta, cpass, cfail);
951     }
952    
953     yval[ibin] = eff;
954     yerrl[ibin] = errl;
955     yerrh[ibin] = errh;
956     }
957     delete cpass;
958     delete cfail;
959    
960     return new TGraphAsymmErrors(n,xval,yval,xerr,xerr,yerrl,yerrh);
961     }
962    
963     //--------------------------------------------------------------------------------------------------
964     void makeEffHist2D(TH2D *hEff, TH2D *hErrl, TH2D *hErrh, const vector<TTree*> &passv, const vector<TTree*> &failv, const Int_t method,
965     const TString name, const Double_t massLo, const Double_t massHi, const TString format, const Bool_t doAbsEta)
966     {
967     TCanvas *cpass = MakeCanvas("cpass","cpass",720,540);
968     cpass->SetWindowPosition(cpass->GetWindowTopX()+cpass->GetBorderSize()+800,0);
969     TCanvas *cfail = MakeCanvas("cfail","cfail",720,540);
970     cfail->SetWindowPosition(cfail->GetWindowTopX()+cfail->GetBorderSize()+800,cpass->GetWindowTopX()+cfail->GetBorderSize()+540);
971    
972     for(Int_t iy=0; iy<hEff->GetNbinsY(); iy++) {
973     for(Int_t ix=0; ix<hEff->GetNbinsX(); ix++) {
974     Int_t ibin = iy*(hEff->GetNbinsX()) + ix;
975    
976     Double_t eff, errl, errh;
977     performCount(eff, errl, errh, ibin,
978     hEff->GetXaxis()->GetBinLowEdge(ix+1), hEff->GetXaxis()->GetBinLowEdge(ix+2),
979     hEff->GetYaxis()->GetBinLowEdge(iy+1), hEff->GetYaxis()->GetBinLowEdge(iy+2),
980     passv[ibin], failv[ibin], method,
981     name, massLo, massHi, format, doAbsEta,
982     cpass, cfail);
983    
984     hEff ->SetCellContent(ix+1, iy+1, eff);
985     hErrl->SetCellContent(ix+1, iy+1, errl);
986     hErrh->SetCellContent(ix+1, iy+1, errh);
987     }
988     }
989     delete cpass;
990     delete cfail;
991     }
992    
993     void makeEffHist2D(TH2D *hEff, TH2D *hErrl, TH2D *hErrh, const vector<TTree*> &passv, const vector<TTree*> &failv,
994     const Int_t sigpass, const Int_t bkgpass, const Int_t sigfail, const Int_t bkgfail,
995     const TString name, const Double_t massLo, const Double_t massHi, const Double_t fitMassLo, const Double_t fitMassHi,
996     const TString format, const Bool_t doAbsEta)
997     {
998     TCanvas *cpass = MakeCanvas("cpass","cpass",720,540);
999     cpass->SetWindowPosition(cpass->GetWindowTopX()+cpass->GetBorderSize()+800,0);
1000     TCanvas *cfail = MakeCanvas("cfail","cfail",720,540);
1001     cfail->SetWindowPosition(cfail->GetWindowTopX()+cfail->GetBorderSize()+800,cpass->GetWindowTopX()+cfail->GetBorderSize()+540);
1002    
1003     for(Int_t iy=0; iy<hEff->GetNbinsY(); iy++) {
1004     for(Int_t ix=0; ix<hEff->GetNbinsX(); ix++) {
1005     Int_t ibin = iy*(hEff->GetNbinsX()) + ix;
1006    
1007     ifstream rfile;
1008     char rname[100];
1009     sprintf(rname,"%s/fitres%s_%i.txt",sOutDir.Data(),name.Data(),ibin);
1010     rfile.open(rname);
1011    
1012     Double_t eff, errl, errh;
1013     if(rfile.is_open()) {
1014     parseFitResults(rfile,eff,errl,errh);
1015     rfile.close();
1016    
1017     } else {
1018     performFit(eff, errl, errh, ibin,
1019     hEff->GetXaxis()->GetBinLowEdge(ix+1), hEff->GetXaxis()->GetBinLowEdge(ix+2),
1020     hEff->GetYaxis()->GetBinLowEdge(iy+1), hEff->GetYaxis()->GetBinLowEdge(iy+2),
1021     passv[ibin], failv[ibin],
1022     sigpass, bkgpass, sigfail, bkgfail,
1023     name, massLo, massHi, fitMassLo, fitMassHi,
1024     format, doAbsEta, cpass, cfail);
1025     }
1026     hEff ->SetCellContent(ix+1, iy+1, eff);
1027     hErrl->SetCellContent(ix+1, iy+1, errl);
1028     hErrh->SetCellContent(ix+1, iy+1, errh);
1029     }
1030     }
1031     delete cpass;
1032     delete cfail;
1033     }
1034    
1035     //--------------------------------------------------------------------------------------------------
1036     void generateHistTemplates(const TString infilename,
1037     const vector<Double_t> &ptEdgesv, const vector<Double_t> &etaEdgesv, const vector<Double_t> &phiEdgesv, const vector<Double_t> &npvEdgesv,
1038     const Double_t fitMassLo, const Double_t fitMassHi, const Bool_t doAbsEta, const Int_t charge, const TH1D* puWeights)
1039     {
1040     cout << "Creating histogram templates... "; cout.flush();
1041    
1042     char hname[50];
1043    
1044     const UInt_t ptNbins = ptEdgesv.size()-1;
1045     const UInt_t etaNbins = etaEdgesv.size()-1;
1046     const UInt_t phiNbins = phiEdgesv.size()-1;
1047     const UInt_t npvNbins = npvEdgesv.size()-1;
1048    
1049     TH1D* passPt[ptNbins];
1050     TH1D* failPt[ptNbins];
1051     for(UInt_t ibin=0; ibin<ptNbins; ibin++) {
1052     sprintf(hname,"passpt_%i",ibin);
1053     passPt[ibin] = new TH1D(hname,"",Int_t((fitMassHi-fitMassLo)/BIN_SIZE_PASS),fitMassLo,fitMassHi);
1054     passPt[ibin]->SetDirectory(0);
1055     sprintf(hname,"failpt_%i",ibin);
1056     failPt[ibin] = new TH1D(hname,"",Int_t((fitMassHi-fitMassLo)/BIN_SIZE_FAIL),fitMassLo,fitMassHi);
1057     failPt[ibin]->SetDirectory(0);
1058     }
1059    
1060     TH1D* passEta[etaNbins];
1061     TH1D* failEta[etaNbins];
1062     for(UInt_t ibin=0; ibin<etaNbins; ibin++) {
1063     sprintf(hname,"passeta_%i",ibin);
1064     passEta[ibin] = new TH1D(hname,"",Int_t((fitMassHi-fitMassLo)/BIN_SIZE_PASS),fitMassLo,fitMassHi);
1065     passEta[ibin]->SetDirectory(0);
1066     sprintf(hname,"faileta_%i",ibin);
1067     failEta[ibin] = new TH1D(hname,"",Int_t((fitMassHi-fitMassLo)/BIN_SIZE_FAIL),fitMassLo,fitMassHi);
1068     failEta[ibin]->SetDirectory(0);
1069     }
1070    
1071     TH1D* passPhi[phiNbins];
1072     TH1D* failPhi[phiNbins];
1073     for(UInt_t ibin=0; ibin<phiNbins; ibin++) {
1074     sprintf(hname,"passphi_%i",ibin);
1075     passPhi[ibin] = new TH1D(hname,"",Int_t((fitMassHi-fitMassLo)/BIN_SIZE_PASS),fitMassLo,fitMassHi);
1076     passPhi[ibin]->SetDirectory(0);
1077     sprintf(hname,"failphi_%i",ibin);
1078     failPhi[ibin] = new TH1D(hname,"",Int_t((fitMassHi-fitMassLo)/BIN_SIZE_FAIL),fitMassLo,fitMassHi);
1079     failPhi[ibin]->SetDirectory(0);
1080     }
1081    
1082     TH1D* passEtaPt[etaNbins*ptNbins];
1083     TH1D* failEtaPt[etaNbins*ptNbins];
1084     for(UInt_t ibin=0; ibin<(etaNbins*ptNbins); ibin++) {
1085     sprintf(hname,"passetapt_%i",ibin);
1086     passEtaPt[ibin] = new TH1D(hname,"",Int_t((fitMassHi-fitMassLo)/BIN_SIZE_PASS),fitMassLo,fitMassHi);
1087     passEtaPt[ibin]->SetDirectory(0);
1088     sprintf(hname,"failetapt_%i",ibin);
1089     failEtaPt[ibin] = new TH1D(hname,"",Int_t((fitMassHi-fitMassLo)/BIN_SIZE_FAIL),fitMassLo,fitMassHi);
1090     failEtaPt[ibin]->SetDirectory(0);
1091     }
1092    
1093     TH1D* passEtaPhi[etaNbins*phiNbins];
1094     TH1D* failEtaPhi[etaNbins*phiNbins];
1095     for(UInt_t ibin=0; ibin<(etaNbins*phiNbins); ibin++) {
1096     sprintf(hname,"passetaphi_%i",ibin);
1097     passEtaPhi[ibin] = new TH1D(hname,"",Int_t((fitMassHi-fitMassLo)/BIN_SIZE_PASS),fitMassLo,fitMassHi);
1098     passEtaPhi[ibin]->SetDirectory(0);
1099     sprintf(hname,"failetaphi_%i",ibin);
1100     failEtaPhi[ibin] = new TH1D(hname,"",Int_t((fitMassHi-fitMassLo)/BIN_SIZE_FAIL),fitMassLo,fitMassHi);
1101     failEtaPhi[ibin]->SetDirectory(0);
1102     }
1103    
1104     TH1D* passNPV[npvNbins];
1105     TH1D* failNPV[npvNbins];
1106     for(UInt_t ibin=0; ibin<npvNbins; ibin++) {
1107     sprintf(hname,"passnpv_%i",ibin);
1108     passNPV[ibin] = new TH1D(hname,"",Int_t((fitMassHi-fitMassLo)/BIN_SIZE_PASS),fitMassLo,fitMassHi);
1109     passNPV[ibin]->SetDirectory(0);
1110     sprintf(hname,"failnpv_%i",ibin);
1111     failNPV[ibin] = new TH1D(hname,"",Int_t((fitMassHi-fitMassLo)/BIN_SIZE_FAIL),fitMassLo,fitMassHi);
1112     failNPV[ibin]->SetDirectory(0);
1113     }
1114    
1115     TFile infile(infilename);
1116     TTree *intree = (TTree*)infile.Get("Events");
1117     EffData data;
1118     intree->SetBranchAddress("Events",&data);
1119    
1120     for(UInt_t ientry=0; ientry<intree->GetEntries(); ientry++) {
1121     intree->GetEntry(ientry);
1122    
1123     Double_t puWgt=1;
1124     if(puWeights)
1125     puWgt = puWeights->GetBinContent(data.npu+1);
1126    
1127     if((data.q)*charge < 0) continue;
1128    
1129     Int_t ipt=-1;
1130     for(UInt_t ibin=0; ibin<ptNbins; ibin++)
1131     if((data.pt >= ptEdgesv[ibin]) && (data.pt < ptEdgesv[ibin+1]))
1132     ipt = ibin;
1133     if(ipt<0) continue;
1134    
1135     Int_t ieta=-1;
1136     for(UInt_t ibin=0; ibin<etaNbins; ibin++) {
1137     if(doAbsEta) {
1138     assert(etaEdgesv[ibin]>=0);
1139     if((fabs(data.eta) >= etaEdgesv[ibin]) && (fabs(data.eta) < etaEdgesv[ibin+1]))
1140     ieta = ibin;
1141     } else {
1142     if((data.eta >= etaEdgesv[ibin]) && (data.eta < etaEdgesv[ibin+1]))
1143     ieta = ibin;
1144     }
1145     }
1146     if(ieta<0) continue;
1147    
1148     Int_t iphi=-1;
1149     for(UInt_t ibin=0; ibin<phiNbins; ibin++)
1150     if((data.phi >= phiEdgesv[ibin]) && (data.phi < phiEdgesv[ibin+1]))
1151     iphi = ibin;
1152     if(iphi<0) continue;
1153    
1154     Int_t inpv=-1;
1155     for(UInt_t ibin=0; ibin<npvNbins; ibin++)
1156     if((data.npv >= npvEdgesv[ibin]) && (data.npv < npvEdgesv[ibin+1]))
1157     inpv = ibin;
1158     if(inpv<0) continue;
1159    
1160     if(data.pass) {
1161     passPt[ipt]->Fill(data.mass,puWgt);
1162     passEta[ieta]->Fill(data.mass,puWgt);
1163     passPhi[iphi]->Fill(data.mass,puWgt);
1164     passEtaPt[ipt*etaNbins + ieta]->Fill(data.mass,puWgt);
1165     passEtaPhi[iphi*etaNbins + ieta]->Fill(data.mass,puWgt);
1166     passNPV[inpv]->Fill(data.mass,puWgt);
1167     } else {
1168     failPt[ipt]->Fill(data.mass,puWgt);
1169     failEta[ieta]->Fill(data.mass,puWgt);
1170     failPhi[iphi]->Fill(data.mass,puWgt);
1171     failEtaPt[ipt*etaNbins + ieta]->Fill(data.mass,puWgt);
1172     failEtaPhi[iphi*etaNbins + ieta]->Fill(data.mass,puWgt);
1173     failNPV[inpv]->Fill(data.mass,puWgt);
1174     }
1175     }
1176     infile.Close();
1177    
1178     TFile outfile("histTemplates.root", "RECREATE");
1179     for(UInt_t ibin=0; ibin<ptNbins; ibin++) {
1180     passPt[ibin]->Write();
1181     failPt[ibin]->Write();
1182     delete passPt[ibin];
1183     delete failPt[ibin];
1184     }
1185     for(UInt_t ibin=0; ibin<etaNbins; ibin++) {
1186     passEta[ibin]->Write();
1187     failEta[ibin]->Write();
1188     delete passEta[ibin];
1189     delete failEta[ibin];
1190     }
1191     for(UInt_t ibin=0; ibin<phiNbins; ibin++) {
1192     passPhi[ibin]->Write();
1193     failPhi[ibin]->Write();
1194     delete passPhi[ibin];
1195     delete failPhi[ibin];
1196     }
1197     for(UInt_t ibin=0; ibin<(etaNbins*ptNbins); ibin++) {
1198     passEtaPt[ibin]->Write();
1199     failEtaPt[ibin]->Write();
1200     delete passEtaPt[ibin];
1201     delete failEtaPt[ibin];
1202     }
1203     for(UInt_t ibin=0; ibin<(etaNbins*phiNbins); ibin++) {
1204     passEtaPhi[ibin]->Write();
1205     failEtaPhi[ibin]->Write();
1206     delete passEtaPhi[ibin];
1207     delete failEtaPhi[ibin];
1208     }
1209     for(UInt_t ibin=0; ibin<npvNbins; ibin++) {
1210     passNPV[ibin]->Write();
1211     failNPV[ibin]->Write();
1212     delete passNPV[ibin];
1213     delete failNPV[ibin];
1214     }
1215     outfile.Write();
1216     outfile.Close();
1217    
1218     cout << "Done!" << endl;
1219     }
1220    
1221     //--------------------------------------------------------------------------------------------------
1222     void generateDataTemplates(const TString infilename,
1223     const vector<Double_t> &ptEdgesv, const vector<Double_t> &etaEdgesv, const vector<Double_t> &phiEdgesv, const vector<Double_t> &npvEdgesv,
1224     const Double_t fitMassLo, const Double_t fitMassHi, const Bool_t doAbsEta, const Int_t charge)
1225     {
1226     cout << "Creating data templates... "; cout.flush();
1227    
1228     char tname[50];
1229    
1230     const UInt_t ptNbins = ptEdgesv.size()-1;
1231     const UInt_t etaNbins = etaEdgesv.size()-1;
1232     const UInt_t phiNbins = phiEdgesv.size()-1;
1233     const UInt_t npvNbins = npvEdgesv.size()-1;
1234    
1235     Float_t mass;
1236    
1237     TTree* passPt[ptNbins];
1238     TTree* failPt[ptNbins];
1239     for(UInt_t ibin=0; ibin<ptNbins; ibin++) {
1240     sprintf(tname,"passpt_%i",ibin);
1241     passPt[ibin] = new TTree(tname,"");
1242     passPt[ibin]->Branch("m",&mass,"m/F");
1243     passPt[ibin]->SetDirectory(0);
1244     sprintf(tname,"failpt_%i",ibin);
1245     failPt[ibin] = new TTree(tname,"");
1246     failPt[ibin]->Branch("m",&mass,"m/F");
1247     failPt[ibin]->SetDirectory(0);
1248     }
1249    
1250     TTree* passEta[etaNbins];
1251     TTree* failEta[etaNbins];
1252     for(UInt_t ibin=0; ibin<etaNbins; ibin++) {
1253     sprintf(tname,"passeta_%i",ibin);
1254     passEta[ibin] = new TTree(tname,"");
1255     passEta[ibin]->Branch("m",&mass,"m/F");
1256     passEta[ibin]->SetDirectory(0);
1257     sprintf(tname,"faileta_%i",ibin);
1258     failEta[ibin] = new TTree(tname,"");
1259     failEta[ibin]->Branch("m",&mass,"m/F");
1260     failEta[ibin]->SetDirectory(0);
1261     }
1262    
1263     TTree* passPhi[phiNbins];
1264     TTree* failPhi[phiNbins];
1265     for(UInt_t ibin=0; ibin<phiNbins; ibin++) {
1266     sprintf(tname,"passphi_%i",ibin);
1267     passPhi[ibin] = new TTree(tname,"");
1268     passPhi[ibin]->Branch("m",&mass,"m/F");
1269     passPhi[ibin]->SetDirectory(0);
1270     sprintf(tname,"failphi_%i",ibin);
1271     failPhi[ibin] = new TTree(tname,"");
1272     failPhi[ibin]->Branch("m",&mass,"m/F");
1273     failPhi[ibin]->SetDirectory(0);
1274     }
1275    
1276     TTree* passEtaPt[etaNbins*ptNbins];
1277     TTree* failEtaPt[etaNbins*ptNbins];
1278     for(UInt_t ibin=0; ibin<(etaNbins*ptNbins); ibin++) {
1279     sprintf(tname,"passetapt_%i",ibin);
1280     passEtaPt[ibin] = new TTree(tname,"");
1281     passEtaPt[ibin]->Branch("m",&mass,"m/F");
1282     passEtaPt[ibin]->SetDirectory(0);
1283     sprintf(tname,"failetapt_%i",ibin);
1284     failEtaPt[ibin] = new TTree(tname,"");
1285     failEtaPt[ibin]->Branch("m",&mass,"m/F");
1286     failEtaPt[ibin]->SetDirectory(0);
1287     }
1288    
1289     TTree* passEtaPhi[etaNbins*phiNbins];
1290     TTree* failEtaPhi[etaNbins*phiNbins];
1291     for(UInt_t ibin=0; ibin<(etaNbins*phiNbins); ibin++) {
1292     sprintf(tname,"passetaphi_%i",ibin);
1293     passEtaPhi[ibin] = new TTree(tname,"");
1294     passEtaPhi[ibin]->Branch("m",&mass,"m/F");
1295     passEtaPhi[ibin]->SetDirectory(0);
1296     sprintf(tname,"failetaphi_%i",ibin);
1297     failEtaPhi[ibin] = new TTree(tname,"");
1298     failEtaPhi[ibin]->Branch("m",&mass,"m/F");
1299     failEtaPhi[ibin]->SetDirectory(0);
1300     }
1301    
1302     TTree* passNPV[npvNbins];
1303     TTree* failNPV[npvNbins];
1304     for(UInt_t ibin=0; ibin<npvNbins; ibin++) {
1305     sprintf(tname,"passnpv_%i",ibin);
1306     passNPV[ibin] = new TTree(tname,"");
1307     passNPV[ibin]->Branch("m",&mass,"m/F");
1308     passNPV[ibin]->SetDirectory(0);
1309     sprintf(tname,"failnpv_%i",ibin);
1310     failNPV[ibin] = new TTree(tname,"");
1311     failNPV[ibin]->Branch("m",&mass,"m/F");
1312     failNPV[ibin]->SetDirectory(0);
1313     }
1314    
1315     TFile infile(infilename);
1316     TTree *intree = (TTree*)infile.Get("Events");
1317     EffData data;
1318     intree->SetBranchAddress("Events",&data);
1319    
1320     for(UInt_t ientry=0; ientry<intree->GetEntries(); ientry++) {
1321     intree->GetEntry(ientry);
1322    
1323     if((data.q)*charge < 0) continue;
1324     if(data.mass < fitMassLo) continue;
1325     if(data.mass > fitMassHi) continue;
1326    
1327     mass = data.mass;
1328    
1329     Int_t ipt=-1;
1330     for(UInt_t ibin=0; ibin<ptNbins; ibin++)
1331     if((data.pt >= ptEdgesv[ibin]) && (data.pt < ptEdgesv[ibin+1]))
1332     ipt = ibin;
1333     if(ipt<0) continue;
1334    
1335     Int_t ieta=-1;
1336     for(UInt_t ibin=0; ibin<etaNbins; ibin++) {
1337     if(doAbsEta) {
1338     assert(etaEdgesv[ibin]>=0);
1339     if((fabs(data.eta) >= etaEdgesv[ibin]) && (fabs(data.eta) < etaEdgesv[ibin+1]))
1340     ieta = ibin;
1341     } else {
1342     if((data.eta >= etaEdgesv[ibin]) && (data.eta < etaEdgesv[ibin+1]))
1343     ieta = ibin;
1344     }
1345     }
1346     if(ieta<0) continue;
1347    
1348     Int_t iphi=-1;
1349     for(UInt_t ibin=0; ibin<phiNbins; ibin++)
1350     if((data.phi >= phiEdgesv[ibin]) && (data.phi < phiEdgesv[ibin+1]))
1351     iphi = ibin;
1352     if(iphi<0) continue;
1353    
1354     Int_t inpv=-1;
1355     for(UInt_t ibin=0; ibin<npvNbins; ibin++)
1356     if((data.npv >= npvEdgesv[ibin]) && (data.npv < npvEdgesv[ibin+1]))
1357     inpv = ibin;
1358     if(inpv<0) continue;
1359    
1360     if(data.pass) {
1361     passPt[ipt]->Fill();
1362     passEta[ieta]->Fill();
1363     passPhi[iphi]->Fill();
1364     passEtaPt[ipt*etaNbins + ieta]->Fill();
1365     passEtaPhi[iphi*etaNbins + ieta]->Fill();
1366     passNPV[inpv]->Fill();
1367     } else {
1368     failPt[ipt]->Fill();
1369     failEta[ieta]->Fill();
1370     failPhi[iphi]->Fill();
1371     failEtaPt[ipt*etaNbins + ieta]->Fill();
1372     failEtaPhi[iphi*etaNbins + ieta]->Fill();
1373     failNPV[inpv]->Fill();
1374     }
1375     }
1376     infile.Close();
1377    
1378     TFile outfile("dataTemplates.root", "RECREATE");
1379     for(UInt_t ibin=0; ibin<ptNbins; ibin++) {
1380     passPt[ibin]->Write();
1381     failPt[ibin]->Write();
1382     delete passPt[ibin];
1383     delete failPt[ibin];
1384     }
1385     for(UInt_t ibin=0; ibin<etaNbins; ibin++) {
1386     passEta[ibin]->Write();
1387     failEta[ibin]->Write();
1388     delete passEta[ibin];
1389     delete failEta[ibin];
1390     }
1391     for(UInt_t ibin=0; ibin<phiNbins; ibin++) {
1392     passPhi[ibin]->Write();
1393     failPhi[ibin]->Write();
1394     delete passPhi[ibin];
1395     delete failPhi[ibin];
1396     }
1397     for(UInt_t ibin=0; ibin<(etaNbins*ptNbins); ibin++) {
1398     passEtaPt[ibin]->Write();
1399     failEtaPt[ibin]->Write();
1400     delete passEtaPt[ibin];
1401     delete failEtaPt[ibin];
1402     }
1403     for(UInt_t ibin=0; ibin<(etaNbins*phiNbins); ibin++) {
1404     passEtaPhi[ibin]->Write();
1405     failEtaPhi[ibin]->Write();
1406     delete passEtaPhi[ibin];
1407     delete failEtaPhi[ibin];
1408     }
1409     for(UInt_t ibin=0; ibin<npvNbins; ibin++) {
1410     passNPV[ibin]->Write();
1411     failNPV[ibin]->Write();
1412     delete passNPV[ibin];
1413     delete failNPV[ibin];
1414     }
1415     outfile.Write();
1416     outfile.Close();
1417    
1418     cout << "Done!" << endl;
1419     }
1420    
1421     //--------------------------------------------------------------------------------------------------
1422     void performCount(Double_t &resEff, Double_t &resErrl, Double_t &resErrh,
1423     const Int_t ibin, const Double_t xbinLo, const Double_t xbinHi, const Double_t ybinLo, const Double_t ybinHi,
1424     TTree *passTree, TTree *failTree, const Int_t method,
1425     const TString name, const Double_t massLo, const Double_t massHi, const TString format, const Bool_t doAbsEta,
1426     TCanvas *cpass, TCanvas *cfail)
1427     {
1428     Float_t m,w;
1429     char pname[50];
1430     char binlabelx[100];
1431     char binlabely[100];
1432     char yield[50];
1433     char ylabel[50];
1434     char effstr[100];
1435    
1436     Double_t npass=0, ntotal=0;
1437     passTree->SetBranchAddress("m",&m);
1438     passTree->SetBranchAddress("w",&w);
1439     for(UInt_t ientry=0; ientry<passTree->GetEntries(); ientry++) {
1440     passTree->GetEntry(ientry);
1441     if(m<massLo || m>massHi) continue;
1442     npass+=w;
1443     ntotal+=w;
1444     }
1445     failTree->SetBranchAddress("m",&m);
1446     failTree->SetBranchAddress("w",&w);
1447     for(UInt_t ientry=0; ientry<failTree->GetEntries(); ientry++) {
1448     failTree->GetEntry(ientry);
1449     if(m<massLo || m>massHi) continue;
1450     ntotal+=w;
1451     }
1452     resEff = (ntotal>0) ? npass/ntotal : 0;
1453     if(method==0) {
1454     resErrl = resEff - TEfficiency::ClopperPearson((UInt_t)ntotal, (UInt_t)npass, 0.68269, kFALSE);
1455     resErrh = TEfficiency::ClopperPearson((UInt_t)ntotal, (UInt_t)npass, 0.68269, kTRUE) - resEff;
1456     }
1457    
1458     if(name.CompareTo("pt")==0) {
1459     sprintf(binlabelx,"%i GeV/c < p_{T} < %i GeV/c",Int_t(xbinLo),Int_t(xbinHi));
1460    
1461     } else if(name.CompareTo("eta")==0) {
1462     if(doAbsEta) sprintf(binlabelx,"%.1f < |#eta| < %.1f",xbinLo,xbinHi);
1463     else sprintf(binlabelx,"%.1f < #eta < %.1f",xbinLo,xbinHi);
1464    
1465     } else if(name.CompareTo("phi")==0) {
1466     sprintf(binlabelx,"%.1f < #phi < %.1f",xbinLo,xbinHi);
1467    
1468     } else if(name.CompareTo("etapt")==0) {
1469     if(doAbsEta) sprintf(binlabelx,"%.1f < |#eta| < %.1f",xbinLo,xbinHi);
1470     else sprintf(binlabelx,"%.1f < #eta < %.1f",xbinLo,xbinHi);
1471     sprintf(binlabely,"%i GeV/c < p_{T} < %i GeV/c",Int_t(ybinLo),Int_t(ybinHi));
1472    
1473     } else if(name.CompareTo("etaphi")==0) {
1474     if(doAbsEta) sprintf(binlabelx,"%.1f < |#eta| < %.1f",xbinLo,xbinHi);
1475     else sprintf(binlabelx,"%.1f < #eta < %.1f",xbinLo,xbinHi);
1476     sprintf(binlabely,"%.1f < #phi < %.1f",ybinLo,ybinHi);
1477    
1478     } else if(name.CompareTo("npv")==0) {
1479     sprintf(binlabelx,"%i #leq N_{PV} < %i",(Int_t)xbinLo,(Int_t)xbinHi);
1480    
1481     }
1482     sprintf(effstr,"#varepsilon = %.4f_{ -%.4f}^{ +%.4f}",resEff,resErrl,resErrh);
1483    
1484     //
1485     // Plot passing probes
1486     //
1487     TH1D *hpass = new TH1D("hpass","",Int_t(massHi-massLo)/BIN_SIZE_PASS,massLo,massHi);
1488     passTree->SetBranchAddress("m",&m);
1489     passTree->SetBranchAddress("w",&w);
1490     hpass->Sumw2();
1491     for(UInt_t ientry=0; ientry<passTree->GetEntries(); ientry++) {
1492     passTree->GetEntry(ientry);
1493     hpass->Fill(m,w);
1494     }
1495     sprintf(pname,"pass%s_%i",name.Data(),ibin);
1496     sprintf(yield,"%i Events",(UInt_t)npass);
1497     sprintf(ylabel,"Events / %.1f GeV/c^{2}",(Double_t)BIN_SIZE_PASS);
1498     CPlot plotPass(pname,"Passing probes","tag-probe mass [GeV/c^{2}]",ylabel,sOutDir);
1499     plotPass.AddHist1D(hpass,"E");
1500     plotPass.AddTextBox(binlabelx,0.21,0.85,0.51,0.90,0,kBlack,-1);
1501     if((name.CompareTo("etapt")==0) || (name.CompareTo("etaphi")==0)) {
1502     plotPass.AddTextBox(binlabely,0.21,0.80,0.51,0.85,0,kBlack,-1);
1503     plotPass.AddTextBox(yield,0.21,0.76,0.51,0.80,0,kBlack,-1);
1504     } else {
1505     plotPass.AddTextBox(yield,0.21,0.81,0.51,0.85,0,kBlack,-1);
1506     }
1507     plotPass.AddTextBox(effstr,0.70,0.85,0.95,0.90,0,kBlack,-1);
1508     plotPass.Draw(cpass,kTRUE,format);
1509    
1510     //
1511     // Plot failing probes
1512     //
1513     TH1D *hfail = new TH1D("hfail","",Int_t(massHi-massLo)/BIN_SIZE_FAIL,massLo,massHi);
1514     hfail->Sumw2();
1515     failTree->SetBranchAddress("m",&m);
1516     failTree->SetBranchAddress("w",&w);
1517     for(UInt_t ientry=0; ientry<failTree->GetEntries(); ientry++) {
1518     failTree->GetEntry(ientry);
1519     hfail->Fill(m,w);
1520     }
1521     sprintf(pname,"fail%s_%i",name.Data(),ibin);
1522     sprintf(yield,"%i Events",(UInt_t)(ntotal-npass));
1523     sprintf(ylabel,"Events / %.1f GeV/c^{2}",(Double_t)BIN_SIZE_FAIL);
1524     CPlot plotFail(pname,"Failing probes","tag-probe mass [GeV/c^{2}]",ylabel,sOutDir);
1525     plotFail.AddHist1D(hfail,"E");
1526     plotFail.AddTextBox(binlabelx,0.21,0.85,0.51,0.90,0,kBlack,-1);
1527     if((name.CompareTo("etapt")==0) || (name.CompareTo("etaphi")==0)) {
1528     plotFail.AddTextBox(binlabely,0.21,0.80,0.51,0.85,0,kBlack,-1);
1529     plotFail.AddTextBox(yield,0.21,0.76,0.51,0.80,0,kBlack,-1);
1530     } else {
1531     plotFail.AddTextBox(yield,0.21,0.81,0.51,0.85,0,kBlack,-1);
1532     }
1533     plotFail.AddTextBox(effstr,0.70,0.85,0.95,0.90,0,kBlack,-1);
1534     plotFail.Draw(cfail,kTRUE,format);
1535    
1536     delete hpass;
1537     delete hfail;
1538     }
1539    
1540     //--------------------------------------------------------------------------------------------------
1541     void performFit(Double_t &resEff, Double_t &resErrl, Double_t &resErrh,
1542     const Int_t ibin, const Double_t xbinLo, const Double_t xbinHi, const Double_t ybinLo, const Double_t ybinHi,
1543     TTree *passTree, TTree *failTree,
1544     const Int_t sigpass, const Int_t bkgpass, const Int_t sigfail, const Int_t bkgfail,
1545     const TString name, const Double_t massLo, const Double_t massHi, const Double_t fitMassLo, const Double_t fitMassHi,
1546     const TString format, const Bool_t doAbsEta, TCanvas *cpass, TCanvas *cfail)
1547     {
1548     RooRealVar m("m","mass",fitMassLo,fitMassHi);
1549     m.setBins(10000);
1550    
1551     char pname[50];
1552     char binlabelx[100];
1553     char binlabely[100];
1554     char yield[50];
1555     char ylabel[50];
1556     char effstr[100];
1557     char nsigstr[100];
1558     char nbkgstr[100];
1559     char chi2str[100];
1560    
1561     Int_t nflpass=0, nflfail=0;
1562    
1563     TFile *histfile = 0;
1564     if(sigpass==2 || sigfail==2) {
1565     histfile = new TFile("histTemplates.root");
1566     assert(histfile);
1567     }
1568     TFile *datfile = 0;
1569     if(sigpass==4 || sigfail==4) {
1570     datfile = new TFile("dataTemplates.root");
1571     assert(datfile);
1572     }
1573    
1574     // Define categories
1575     RooCategory sample("sample","");
1576     sample.defineType("Pass",1);
1577     sample.defineType("Fail",2);
1578    
1579     RooAbsData *dataPass=0;
1580     RooAbsData *dataFail=0;
1581     TH1D histPass("histPass","",Int_t(fitMassHi-fitMassLo)/BIN_SIZE_PASS,fitMassLo,fitMassHi);
1582     TH1D histFail("histFail","",Int_t(fitMassHi-fitMassLo)/BIN_SIZE_FAIL,fitMassLo,fitMassHi);
1583     RooAbsData *dataCombined=0;
1584    
1585     const Bool_t doBinned = kTRUE;//(passTree->GetEntries()>1000 && failTree->GetEntries()>1000);
1586    
1587     if(doBinned) {
1588     passTree->Draw("m>>histPass","w");
1589     failTree->Draw("m>>histFail","w");
1590     dataPass = new RooDataHist("dataPass","dataPass",RooArgSet(m),&histPass);
1591     dataFail = new RooDataHist("dataFail","dataFail",RooArgSet(m),&histFail);
1592     //m.setBins(100);
1593    
1594     dataCombined = new RooDataHist("dataCombined","dataCombined",RooArgList(m),
1595     RooFit::Index(sample),
1596     RooFit::Import("Pass",*((RooDataHist*)dataPass)),
1597     RooFit::Import("Fail",*((RooDataHist*)dataFail)));
1598    
1599     } else {
1600     dataPass = new RooDataSet("dataPass","dataPass",passTree,RooArgSet(m));
1601     dataFail = new RooDataSet("dataFail","dataFail",failTree,RooArgSet(m));
1602    
1603     dataCombined = new RooDataSet("dataCombined","dataCombined",RooArgList(m),
1604     RooFit::Index(sample),
1605     RooFit::Import("Pass",*((RooDataSet*)dataPass)),
1606     RooFit::Import("Fail",*((RooDataSet*)dataFail)));
1607     }
1608    
1609     // Define signal and background models
1610     CSignalModel *sigPass = 0;
1611     CBackgroundModel *bkgPass = 0;
1612     CSignalModel *sigFail = 0;
1613     CBackgroundModel *bkgFail = 0;
1614    
1615     if(sigpass==1) {
1616     sigPass = new CBreitWignerConvCrystalBall(m,kTRUE);
1617     nflpass += 4;
1618    
1619     } else if(sigpass==2) {
1620     char hname[50];
1621     sprintf(hname,"pass%s_%i",name.Data(),ibin);
1622     TH1D *h = (TH1D*)histfile->Get(hname);
1623     assert(h);
1624     sigPass = new CMCTemplateConvGaussian(m,h,kTRUE);
1625     nflpass += 2;
1626    
1627     } else if(sigpass==3) {
1628     sigPass = new CVoigtianCBShape(m,kTRUE);
1629     nflpass += 4;
1630    
1631     } else if(sigpass==4) {
1632     char tname[50];
1633     sprintf(tname,"pass%s_%i",name.Data(),ibin);
1634     TTree *t = (TTree*)datfile->Get(tname);
1635     assert(t);
1636     sigPass = new CMCDatasetConvGaussian(m,t,kTRUE);
1637     nflpass += 2;
1638     }
1639    
1640     if(bkgpass==1) {
1641     bkgPass = new CExponential(m,kTRUE);
1642     nflpass += 1;
1643    
1644     } else if(bkgpass==2) {
1645     bkgPass = new CErfExpo(m,kTRUE);
1646     nflpass += 3;
1647    
1648     } else if(bkgpass==3) {
1649     bkgPass = new CDoubleExp(m,kTRUE);
1650     nflpass += 3;
1651    
1652     } else if(bkgpass==4) {
1653     bkgPass = new CLinearExp(m,kTRUE);
1654     nflpass += 2;
1655    
1656     } else if(bkgpass==5) {
1657     bkgPass = new CQuadraticExp(m,kTRUE);
1658     nflpass += 3;
1659     }
1660    
1661     if(sigfail==1) {
1662     sigFail = new CBreitWignerConvCrystalBall(m,kFALSE);
1663     nflfail += 4;
1664    
1665     } else if(sigfail==2) {
1666     char hname[50];
1667     sprintf(hname,"fail%s_%i",name.Data(),ibin);
1668     TH1D *h = (TH1D*)histfile->Get(hname);
1669     assert(h);
1670     sigFail = new CMCTemplateConvGaussian(m,h,kFALSE);//,((CMCTemplateConvGaussian*)sigPass)->sigma);
1671     nflfail += 2;
1672    
1673     } else if(sigfail==3) {
1674     sigFail = new CVoigtianCBShape(m,kFALSE);
1675     nflfail += 4;
1676    
1677     } else if(sigfail==4) {
1678     char tname[50];
1679     sprintf(tname,"fail%s_%i",name.Data(),ibin);
1680     TTree *t = (TTree*)datfile->Get(tname);
1681     assert(t);
1682     sigFail = new CMCDatasetConvGaussian(m,t,kFALSE);
1683     nflfail += 2;
1684     }
1685    
1686     if(bkgfail==1) {
1687     bkgFail = new CExponential(m,kFALSE);
1688     nflfail += 1;
1689    
1690     } else if(bkgfail==2) {
1691     bkgFail = new CErfExpo(m,kFALSE);
1692     nflfail += 3;
1693    
1694     } else if(bkgfail==3) {
1695     bkgFail = new CDoubleExp(m,kFALSE);
1696     nflfail += 3;
1697    
1698     } else if(bkgfail==4) {
1699     bkgFail = new CLinearExp(m,kFALSE);
1700     nflfail += 2;
1701    
1702     } else if(bkgfail==5) {
1703     bkgFail = new CQuadraticExp(m,kFALSE);
1704     nflfail += 3;
1705     }
1706    
1707     // Define free parameters
1708     Double_t NsigMax = doBinned ? histPass.Integral()+histFail.Integral() : passTree->GetEntries()+failTree->GetEntries();
1709     Double_t NbkgFailMax = doBinned ? histFail.Integral() : failTree->GetEntries();
1710     Double_t NbkgPassMax = doBinned ? histPass.Integral() : passTree->GetEntries();
1711     RooRealVar Nsig("Nsig","Signal Yield",0.80*NsigMax,0,NsigMax);
1712     RooRealVar eff("eff","Efficiency",0.8,0,1.0);
1713     RooRealVar NbkgPass("NbkgPass","Background count in PASS sample",50,0,NbkgPassMax);
1714     if(bkgpass==0) NbkgPass.setVal(0);
1715     RooRealVar NbkgFail("NbkgFail","Background count in FAIL sample",0.1*NbkgFailMax,0.01,NbkgFailMax);
1716    
1717     RooFormulaVar NsigPass("NsigPass","eff*Nsig",RooArgList(eff,Nsig));
1718     RooFormulaVar NsigFail("NsigFail","(1.0-eff)*Nsig",RooArgList(eff,Nsig));
1719     RooAddPdf *modelPass=0, *modelFail=0;
1720     RooExtendPdf *esignalPass=0, *ebackgroundPass=0, *esignalFail=0, *ebackgroundFail=0;
1721     if(massLo!=fitMassLo || massHi!=fitMassHi) {
1722     m.setRange("signalRange",massLo,massHi);
1723    
1724     esignalPass = new RooExtendPdf("esignalPass","esignalPass",*(sigPass->model),NsigPass,"signalRange");
1725     ebackgroundPass = new RooExtendPdf("ebackgroundPass","ebackgroundPass",(bkgpass>0) ? *(bkgPass->model) : *(sigPass->model),NbkgPass,"signalRange");
1726     modelPass = new RooAddPdf("modelPass","Model for PASS sample",(bkgpass>0) ? RooArgList(*esignalPass,*ebackgroundPass) : RooArgList(*esignalPass));
1727    
1728     esignalFail = new RooExtendPdf("esignalFail","esignalFail",*(sigFail->model),NsigFail,"signalRange");
1729     ebackgroundFail = new RooExtendPdf("ebackgroundFail","ebackgroundFail",*(bkgFail->model),NbkgFail,"signalRange");
1730     modelFail = new RooAddPdf("modelFail","Model for FAIL sample", (bkgfail>0) ? RooArgList(*esignalFail,*ebackgroundFail) : RooArgList(*esignalFail));
1731    
1732     } else {
1733     modelPass = new RooAddPdf("modelPass","Model for PASS sample",
1734     (bkgpass>0) ? RooArgList(*(sigPass->model),*(bkgPass->model)) : RooArgList(*(sigPass->model)),
1735     (bkgpass>0) ? RooArgList(NsigPass,NbkgPass) : RooArgList(NsigPass));
1736    
1737     modelFail = new RooAddPdf("modelFail","Model for FAIL sample",RooArgList(*(sigFail->model),*(bkgFail->model)),RooArgList(NsigFail,NbkgFail));
1738     }
1739    
1740     RooSimultaneous totalPdf("totalPdf","totalPdf",sample);
1741     totalPdf.addPdf(*modelPass,"Pass");
1742     totalPdf.addPdf(*modelFail,"Fail");
1743    
1744     RooFitResult *fitResult=0;
1745     fitResult = totalPdf.fitTo(*dataCombined,
1746     RooFit::Extended(),
1747     RooFit::Strategy(2),
1748     //RooFit::Minos(RooArgSet(eff)),
1749     RooFit::Save());
1750    
1751    
1752     // Refit w/o MINOS if MINOS errors are strange...
1753     if((fabs(eff.getErrorLo())<5e-5) || (eff.getErrorHi()<5e-5))
1754     fitResult = totalPdf.fitTo(*dataCombined, RooFit::Extended(), RooFit::Strategy(1), RooFit::Save());
1755    
1756     resEff = eff.getVal();
1757     resErrl = fabs(eff.getErrorLo());
1758     resErrh = eff.getErrorHi();
1759    
1760     if(name.CompareTo("pt")==0) {
1761     sprintf(binlabelx,"%i GeV/c < p_{T} < %i GeV/c",Int_t(xbinLo),Int_t(xbinHi));
1762    
1763     } else if(name.CompareTo("eta")==0) {
1764     if(doAbsEta) sprintf(binlabelx,"%.1f < |#eta| < %.1f",xbinLo,xbinHi);
1765     else sprintf(binlabelx,"%.1f < #eta < %.1f",xbinLo,xbinHi);
1766    
1767     } else if(name.CompareTo("phi")==0) {
1768     sprintf(binlabelx,"%.1f < #phi < %.1f",xbinLo,xbinHi);
1769    
1770     } else if(name.CompareTo("etapt")==0) {
1771     if(doAbsEta) sprintf(binlabelx,"%.1f < |#eta| < %.1f",xbinLo,xbinHi);
1772     else sprintf(binlabelx,"%.1f < #eta < %.1f",xbinLo,xbinHi);
1773     sprintf(binlabely,"%i GeV/c < p_{T} < %i GeV/c",Int_t(ybinLo),Int_t(ybinHi));
1774    
1775     } else if(name.CompareTo("etaphi")==0) {
1776     if(doAbsEta) sprintf(binlabelx,"%.1f < |#eta| < %.1f",xbinLo,xbinHi);
1777     else sprintf(binlabelx,"%.1f < #eta < %.1f",xbinLo,xbinHi);
1778     sprintf(binlabely,"%.1f < #phi < %.1f",ybinLo,ybinHi);
1779    
1780     } else if(name.CompareTo("npv")==0) {
1781     sprintf(binlabelx,"%i #leq N_{PV} < %i",(Int_t)xbinLo,(Int_t)xbinHi);
1782    
1783     }
1784     sprintf(effstr,"#varepsilon = %.4f_{ -%.4f}^{ +%.4f}",eff.getVal(),fabs(eff.getErrorLo()),eff.getErrorHi());
1785    
1786     RooPlot *mframePass = m.frame(Bins(Int_t(fitMassHi-fitMassLo)/BIN_SIZE_PASS));
1787     dataPass->plotOn(mframePass,MarkerStyle(kFullCircle),MarkerSize(0.8),DrawOption("ZP"));
1788     modelPass->plotOn(mframePass);
1789     if(bkgpass>0)
1790     modelPass->plotOn(mframePass,Components("backgroundPass"),LineStyle(kDashed),LineColor(kRed));
1791    
1792    
1793     RooPlot *mframeFail = m.frame(Bins(Int_t(fitMassHi-fitMassLo)/BIN_SIZE_FAIL));
1794     dataFail->plotOn(mframeFail,MarkerStyle(kFullCircle),MarkerSize(0.8),DrawOption("ZP"));
1795     modelFail->plotOn(mframeFail);
1796     modelFail->plotOn(mframeFail,Components("backgroundFail"),LineStyle(kDashed),LineColor(kRed));
1797    
1798     //
1799     // Plot passing probes
1800     //
1801     sprintf(pname,"pass%s_%i",name.Data(),ibin);
1802     sprintf(yield,"%u Events",(Int_t)passTree->GetEntries());
1803     sprintf(ylabel,"Events / %.1f GeV/c^{2}",(Double_t)BIN_SIZE_PASS);
1804     sprintf(nsigstr,"N_{sig} = %.1f #pm %.1f",NsigPass.getVal(),NsigPass.getPropagatedError(*fitResult));
1805     sprintf(chi2str,"#chi^{2}/DOF = %.3f",mframePass->chiSquare(nflpass));
1806     if(bkgpass>0)
1807     sprintf(nbkgstr,"N_{bkg} = %.1f #pm %.1f",NbkgPass.getVal(),NbkgPass.getPropagatedError(*fitResult));
1808     CPlot plotPass(pname,mframePass,"Passing probes","tag-probe mass [GeV/c^{2}]",ylabel,sOutDir);
1809     plotPass.AddTextBox(binlabelx,0.21,0.85,0.51,0.90,0,kBlack,-1);
1810     if((name.CompareTo("etapt")==0) || (name.CompareTo("etaphi")==0)) {
1811     plotPass.AddTextBox(binlabely,0.21,0.80,0.51,0.85,0,kBlack,-1);
1812     plotPass.AddTextBox(yield,0.21,0.76,0.51,0.80,0,kBlack,-1);
1813     } else {
1814     plotPass.AddTextBox(yield,0.21,0.81,0.51,0.85,0,kBlack,-1);
1815     }
1816     plotPass.AddTextBox(effstr,0.70,0.85,0.94,0.90,0,kBlack,-1);
1817     if(bkgpass>0)
1818     plotPass.AddTextBox(0.70,0.68,0.94,0.83,0,kBlack,-1,2,nsigstr,nbkgstr);//,chi2str);
1819     else
1820     plotPass.AddTextBox(0.70,0.73,0.94,0.83,0,kBlack,-1,1,nsigstr);//,chi2str);
1821     plotPass.Draw(cpass,kTRUE,format);
1822    
1823     //
1824     // Plot failing probes
1825     //
1826     sprintf(pname,"fail%s_%i",name.Data(),ibin);
1827     sprintf(yield,"%u Events",(Int_t)failTree->GetEntries());
1828     sprintf(ylabel,"Events / %.1f GeV/c^{2}",(Double_t)BIN_SIZE_FAIL);
1829     sprintf(nsigstr,"N_{sig} = %.1f #pm %.1f",NsigFail.getVal(),NsigFail.getPropagatedError(*fitResult));
1830     sprintf(nbkgstr,"N_{bkg} = %.1f #pm %.1f",NbkgFail.getVal(),NbkgFail.getPropagatedError(*fitResult));
1831     sprintf(chi2str,"#chi^{2}/DOF = %.3f",mframePass->chiSquare(nflfail));
1832     CPlot plotFail(pname,mframeFail,"Failing probes","tag-probe mass [GeV/c^{2}]",ylabel,sOutDir);
1833     plotFail.AddTextBox(binlabelx,0.21,0.85,0.51,0.90,0,kBlack,-1);
1834     if((name.CompareTo("etapt")==0) || (name.CompareTo("etaphi")==0)) {
1835     plotFail.AddTextBox(binlabely,0.21,0.80,0.51,0.85,0,kBlack,-1);
1836     plotFail.AddTextBox(yield,0.21,0.76,0.51,0.80,0,kBlack,-1);
1837     } else {
1838     plotFail.AddTextBox(yield,0.21,0.81,0.51,0.85,0,kBlack,-1);
1839     }
1840     plotFail.AddTextBox(effstr,0.70,0.85,0.94,0.90,0,kBlack,-1);
1841     plotFail.AddTextBox(0.70,0.68,0.94,0.83,0,kBlack,-1,2,nsigstr,nbkgstr);//,chi2str);
1842     plotFail.Draw(cfail,kTRUE,format);
1843    
1844     //
1845     // Write fit results
1846     //
1847     ofstream txtfile;
1848     char txtfname[100];
1849     sprintf(txtfname,"%s/fitres%s_%i.txt",sOutDir.Data(),name.Data(),ibin);
1850     txtfile.open(txtfname);
1851     assert(txtfile.is_open());
1852     fitResult->printStream(txtfile,RooPrintable::kValue,RooPrintable::kVerbose);
1853     txtfile << endl;
1854     printCorrelations(txtfile, fitResult);
1855     txtfile.close();
1856    
1857     //
1858     // Clean up
1859     //
1860     delete esignalPass;
1861     delete ebackgroundPass;
1862     delete esignalFail;
1863     delete ebackgroundFail;
1864     delete modelPass;
1865     delete modelFail;
1866     delete dataCombined;
1867     delete dataPass;
1868     delete dataFail;
1869     delete sigPass;
1870     delete bkgPass;
1871     delete sigFail;
1872     delete bkgFail;
1873     delete histfile;
1874     delete datfile;
1875     }
1876    
1877     //--------------------------------------------------------------------------------------------------
1878     void printCorrelations(ostream& os, RooFitResult *res)
1879     {
1880     ios_base::fmtflags flags = os.flags();
1881     const RooArgList *parlist = res->correlation("eff");
1882    
1883     os << " Correlation Matrix" << endl;
1884     os << " --------------------" << endl;
1885     for(Int_t i=0; i<parlist->getSize(); i++) {
1886     for(Int_t j=0; j<parlist->getSize(); j++)
1887     os << " " << setw(7) << setprecision(4) << fixed << res->correlationMatrix()(i,j);
1888     os << endl;
1889     }
1890     os.flags(flags);
1891     }
1892    
1893     //--------------------------------------------------------------------------------------------------
1894     void parseFitResults(ifstream &ifs, double &eff, double &errl, double &errh)
1895     {
1896     string line;
1897     while(getline(ifs,line)) {
1898     size_t found = line.find("eff");
1899     if(found!=string::npos) {
1900     found = line.find("+/-");
1901     if(found!=string::npos) {
1902     string varname, initval, pmstr;
1903     stringstream ss(line);
1904     ss >> varname >> initval >> eff >> pmstr >> errl;
1905     errh = errl;
1906    
1907     } else {
1908     string varname, initval, errstr;
1909     stringstream ss(line);
1910     ss >> varname >> initval >> eff >> errstr;
1911     size_t ipos = errstr.find(",");
1912     string errlstr = errstr.substr(2,ipos-2);
1913     string errhstr = errstr.substr(ipos+2,errstr.length()-ipos-1);
1914     errl = atof(errlstr.c_str());
1915     errh = atof(errhstr.c_str());
1916     }
1917     }
1918     }
1919     }