1 |
from __future__ import division
|
2 |
|
3 |
from HistGetter import *
|
4 |
from tdrStyle import *
|
5 |
from ROOT import *
|
6 |
from math import pow, exp, sqrt
|
7 |
from copy import deepcopy
|
8 |
from array import array
|
9 |
|
10 |
class QCDEstimator:
|
11 |
luminosity = 36.145#pb-1
|
12 |
mc_luminosity = 36.145#pb-1
|
13 |
luminosity_unit = 'pb-1'
|
14 |
scale = luminosity / mc_luminosity
|
15 |
jetBins = ['0jet', 'allJets', '1jet', '1orMoreJets', '2jets', '2orMoreJets', '3jets', '3orMoreJets', '4orMoreJets']
|
16 |
jetBinsLatex = {'0jet':'0 jet', 'allJets':'#geq 0 jets', '1jet':'1 jet', '1orMoreJets':'#geq 1 jet',
|
17 |
'2jets':'2 jets', '2orMoreJets':'#geq 2 jets', '3jets':'3 jets', '3orMoreJets':'#geq 3 jets',
|
18 |
'4orMoreJets':'#geq 4 jets'}
|
19 |
binWidth = 0.01
|
20 |
rebin = 10
|
21 |
fitRangesClosureTest = [ ( 0.1, 0.9 ), ( 0.1, 1.0 ), ( 0.1, 1.1 ),
|
22 |
( 0.2, 0.9 ), ( 0.2, 1.0 ), ( 0.2, 1.1 ),
|
23 |
( 0.3, 0.9 ), ( 0.3, 1.0 ), ( 0.3, 1.1 )]
|
24 |
|
25 |
fitRangesEstimation = [ ( 0.1, 1.1 ), ( 0.2, 1.1 )]#, ( 0.3, 1.1 )]
|
26 |
signalRegion = ( 0, 0.1 )
|
27 |
maxValue = 1.6
|
28 |
pfIsoHistogramPrefix = 'QCDest_PFIsolation_WithMETCutAndAsymJetCuts_'
|
29 |
pfIsoControlRegionHistogramPrefix = 'QCDest_PFIsolation_controlRegion2_WithMETCutAndAsymJetCuts_'
|
30 |
relIsoHistogramPrefix = 'QCDest_CombRelIso_'
|
31 |
pfIsoResults = {}
|
32 |
relIsoResults = {}
|
33 |
allPfIsoResults = {}
|
34 |
allRelIsoResults = {}
|
35 |
|
36 |
useEntryAsData = 'data'
|
37 |
constrainFit = False
|
38 |
numberOfFreeParameters = 0
|
39 |
|
40 |
currentFitRange = ( 0.1, 1.6 )
|
41 |
currentFitFuntion = 'gaus'
|
42 |
currentJetBin = jetBins[-1]
|
43 |
|
44 |
outputFormat = 'pdf'
|
45 |
outputFolder = ''
|
46 |
|
47 |
def __init__( self, files ):
|
48 |
self.files = files
|
49 |
HistGetter.samplefiles = files
|
50 |
self.histograms = {}
|
51 |
self.histGetter = HistGetter()
|
52 |
self.histGetter.setStyle()
|
53 |
self.getHistograms()
|
54 |
self.applyStyleAndCreateStack()
|
55 |
|
56 |
for bin in self.jetBins:
|
57 |
self.pfIsoResults[bin] = {'actualNumberOfQCDEvents': 0, 'estimatedNumberOfQCDEvents':0,
|
58 |
'fitFunction': None, 'fitParameters': {}, 'numberOfAllDataEvents':0,
|
59 |
'numberOfAllMCEvents':0}
|
60 |
self.relIsoResults[bin] = {'actualNumberOfQCDEvents': 0, 'estimatedNumberOfQCDEvents':0,
|
61 |
'fitFunction': None, 'fitParameters': {}, 'numberOfAllDataEvents':0,
|
62 |
'numberOfAllMCEvents':0}
|
63 |
|
64 |
def getHistograms( self ):
|
65 |
relIsoHists = [self.relIsoHistogramPrefix + jetbin for jetbin in self.jetBins]
|
66 |
pfIsoHists = [self.pfIsoHistogramPrefix + jetbin for jetbin in self.jetBins]
|
67 |
pfIsoControlHists = [self.pfIsoControlRegionHistogramPrefix + jetbin for jetbin in self.jetBins]
|
68 |
allHists = relIsoHists
|
69 |
allHists.extend( pfIsoHists )
|
70 |
allHists.extend( pfIsoControlHists )
|
71 |
HistGetter.hists = allHists
|
72 |
|
73 |
self.histograms = self.histGetter.getHistsFromFiles()
|
74 |
self.histograms = self.histGetter.addSampleSum( self.histograms )
|
75 |
|
76 |
def applyStyleAndCreateStack( self ):
|
77 |
samplesOfInterest = ['data', 'qcd', 'zjets', 'wjets', 'singleTop', 'ttbar', 'allMC']
|
78 |
colors = {'ttbar' : kRed + 1,
|
79 |
'wjets' : kGreen - 3,
|
80 |
'zjets' : kAzure - 2,
|
81 |
'qcd' : kYellow,
|
82 |
'singleTop' : kMagenta}
|
83 |
|
84 |
mcStack = {}
|
85 |
|
86 |
for sample in samplesOfInterest:#sample
|
87 |
for histname in self.histograms[sample].keys():
|
88 |
self.histograms[sample][histname].Rebin( self.rebin )
|
89 |
if not sample in ['data', 'allMC']:
|
90 |
self.histograms[sample][histname].Scale( self.scale )
|
91 |
self.histograms[sample][histname].SetFillStyle( 1001 )
|
92 |
self.histograms[sample][histname].SetFillColor( colors[sample] )
|
93 |
if not mcStack.has_key( histname ):
|
94 |
mcStack[histname] = THStack( "MC_" + histname, "MC_" + histname );
|
95 |
mcStack[histname].Add( self.histograms[sample][histname] )
|
96 |
else:
|
97 |
self.histograms[sample][histname].SetMarkerStyle( 8 );
|
98 |
|
99 |
|
100 |
self.histograms['MCStack'] = mcStack
|
101 |
self.setStyle()
|
102 |
print "=" * 40
|
103 |
print "data integrated luminosity:", self.luminosity, self.luminosity_unit
|
104 |
print "MC integrated luminosity:", self.mc_luminosity, self.luminosity_unit
|
105 |
print "MC scale factor: ", self.scale
|
106 |
print '=' * 40
|
107 |
|
108 |
|
109 |
def setStyle( self ):
|
110 |
tdrstyle = setTDRStyle();
|
111 |
tdrstyle.SetPadRightMargin( 0.05 )#originally was 0.02, too narrow!
|
112 |
tdrStyle.SetStatH( 0.2 );
|
113 |
tdrStyle.SetOptStat( 0 );#off title
|
114 |
tdrStyle.SetOptFit( 0 );#off title
|
115 |
tdrStyle.cd();
|
116 |
gROOT.ForceStyle();
|
117 |
gStyle.SetTitleH( 0.1 );
|
118 |
gStyle.SetStatH( 0.22 ); #0.24);
|
119 |
gStyle.SetStatW( 0.22 ); #0.26);
|
120 |
gStyle.SetOptStat( 1 ); #on stat
|
121 |
gStyle.SetLineScalePS( 2 ); #D=3
|
122 |
gStyle.SetOptFit( 112 );
|
123 |
|
124 |
|
125 |
def doClosureTests( self, function = 'gaus' ):
|
126 |
self.useEntryAsData = 'allMC'
|
127 |
self.currentFitFuntion = function
|
128 |
|
129 |
for fitRange in self.fitRangesClosureTest:
|
130 |
self.currentFitRange = fitRange
|
131 |
for bin in self.jetBins:
|
132 |
self.currentJetBin = bin
|
133 |
self.EstimateJetBin( bin )
|
134 |
self.plot( self.pfIsoHistogramPrefix + bin, self.pfIsoResults[bin] )
|
135 |
self.plot( self.relIsoHistogramPrefix + bin, self.relIsoResults[bin] )
|
136 |
self.allPfIsoResults['%1.1f-%1.1f' % fitRange] = deepcopy( self.pfIsoResults )
|
137 |
self.allRelIsoResults['%1.1f-%1.1f' % fitRange] = deepcopy( self.relIsoResults )
|
138 |
self.plotClosureTest( self.pfIsoHistogramPrefix, self.allPfIsoResults )
|
139 |
self.plotClosureTest( self.relIsoHistogramPrefix, self.allRelIsoResults )
|
140 |
|
141 |
|
142 |
def doEstimate( self, function = 'gaus' ):
|
143 |
self.useEntryAsData = 'data'
|
144 |
self.currentFitFuntion = function
|
145 |
|
146 |
for fitRange in self.fitRangesEstimation:
|
147 |
self.currentFitRange = fitRange
|
148 |
for bin in self.jetBins:
|
149 |
self.currentJetBin = bin
|
150 |
self.EstimateJetBin( bin )
|
151 |
self.plot( self.pfIsoHistogramPrefix + bin, self.pfIsoResults[bin] )
|
152 |
self.plot( self.relIsoHistogramPrefix + bin, self.relIsoResults[bin] )
|
153 |
self.allPfIsoResults['%1.1f-%1.1f' % fitRange] = deepcopy( self.pfIsoResults )
|
154 |
self.allRelIsoResults['%1.1f-%1.1f' % fitRange] = deepcopy( self.relIsoResults )
|
155 |
|
156 |
def EstimateJetBin( self, jetbin ):
|
157 |
# fitRange = self.currentFitRange
|
158 |
function = self.currentFitFuntion
|
159 |
|
160 |
QCD = self.histograms['qcd']
|
161 |
data = self.histograms[self.useEntryAsData]
|
162 |
allMC = self.histograms['allMC']
|
163 |
pfIsoHist = self.pfIsoHistogramPrefix + jetbin
|
164 |
relIsoHist = self.relIsoHistogramPrefix + jetbin
|
165 |
|
166 |
self.pfIsoResults[jetbin]['actualNumberOfQCDEvents'] = QCD[pfIsoHist].GetBinContent(1)
|
167 |
self.pfIsoResults[jetbin]['numberOfAllDataEvents'] = data[pfIsoHist].GetBinContent(1)
|
168 |
self.pfIsoResults[jetbin]['numberOfAllMCEvents'] = allMC[pfIsoHist].GetBinContent(1)
|
169 |
|
170 |
pfIsoFit = self.doFit( data[pfIsoHist] )
|
171 |
self.pfIsoResults[jetbin]['fitFunction'] = pfIsoFit
|
172 |
self.pfIsoResults[jetbin]['fitParameters'] = self.getFitParameters( pfIsoFit )
|
173 |
estimate = 0
|
174 |
if pfIsoFit:
|
175 |
estimate = pfIsoFit.Integral( self.signalRegion[0], self.signalRegion[1] ) / ( self.binWidth * self.rebin )
|
176 |
|
177 |
self.pfIsoResults[jetbin]['estimatedNumberOfQCDEvents'] = estimate
|
178 |
|
179 |
#----------------------------------------------------------------------------------------------------------------------
|
180 |
self.relIsoResults[jetbin]['actualNumberOfQCDEvents'] = QCD[relIsoHist].GetBinContent(1)
|
181 |
self.relIsoResults[jetbin]['numberOfAllDataEvents'] = data[relIsoHist].GetBinContent(1)
|
182 |
self.relIsoResults[jetbin]['numberOfAllMCEvents'] = allMC[relIsoHist].GetBinContent(1)
|
183 |
|
184 |
relIsoFit = self.doFit( data[relIsoHist] )
|
185 |
self.relIsoResults[jetbin]['fitFunction'] = relIsoFit
|
186 |
self.relIsoResults[jetbin]['fitParameters'] = self.getFitParameters( relIsoFit )
|
187 |
|
188 |
estimate = relIsoFit.Integral( self.signalRegion[0], self.signalRegion[1] ) / ( self.binWidth * self.rebin )
|
189 |
self.relIsoResults[jetbin]['estimatedNumberOfQCDEvents'] = estimate
|
190 |
|
191 |
|
192 |
|
193 |
def doFit( self, histogram ):
|
194 |
function = self.currentFitFuntion
|
195 |
fitRange = self.currentFitRange
|
196 |
|
197 |
if not self.constrainFit:
|
198 |
histogram.Fit( function, "Q0", "ah", fitRange[0], fitRange[1] )
|
199 |
|
200 |
else:
|
201 |
ff = TF1( function, function, 0, 1 );
|
202 |
self.numberOfFreeParameters = ff.GetNumberFreeParameters();
|
203 |
|
204 |
return histogram.GetFunction( function )
|
205 |
|
206 |
def plot( self, histname, results ):
|
207 |
data = self.histograms[self.useEntryAsData][histname]
|
208 |
mcStack = self.histograms['MCStack'][histname]
|
209 |
fitFunction = results['fitFunction']
|
210 |
if not fitFunction:
|
211 |
print 'no fitfunction found'
|
212 |
return;
|
213 |
|
214 |
data.GetXaxis().SetRangeUser( 0, self.maxValue - 0.01 );
|
215 |
fitFunction.SetLineColor( kRed );
|
216 |
fitFunction.SetLineWidth( 2 )
|
217 |
|
218 |
fitFunction2 = fitFunction.Clone()
|
219 |
fitFunction2.SetLineColor( kBlue );
|
220 |
fitFunction2.SetRange( self.signalRegion[0], self.signalRegion[1] );
|
221 |
|
222 |
fitFunction3 = fitFunction.Clone()
|
223 |
fitFunction3.SetLineColor( kBlue );
|
224 |
fitFunction3.SetLineStyle( kDashed );
|
225 |
fitFunction3.SetRange( self.signalRegion[1], self.currentFitRange[0] );
|
226 |
|
227 |
canvas = TCanvas( "c1", "Iso fit", 1920, 1080 )
|
228 |
data.Draw();
|
229 |
|
230 |
max = 0
|
231 |
if mcStack.GetMaximum() > data.GetBinContent( 1 ):
|
232 |
max = mcStack.GetMaximum()*1.1
|
233 |
else:
|
234 |
max = data.GetBinContent( 1 ) * 1.1
|
235 |
|
236 |
data.GetYaxis().SetRangeUser( 0, max );
|
237 |
data.SetXTitle( "Relative Isolation" );
|
238 |
data.SetYTitle( "Events/0.1" );
|
239 |
# draw mc
|
240 |
mcStack.Draw( "hist same" );
|
241 |
data.Draw( "ae same" );
|
242 |
|
243 |
fitFunction.Draw( "same" );
|
244 |
fitFunction2.Draw( "same" );
|
245 |
fitFunction3.Draw( "same" );
|
246 |
|
247 |
label = self.add_cms_label( self.currentJetBin )
|
248 |
label.Draw()
|
249 |
|
250 |
legend = self.add_legend( histname )
|
251 |
# legend.Draw()
|
252 |
|
253 |
if self.currentFitFuntion == "pol1":
|
254 |
out = "%s_fit_linear_from_0%.0f_%s" % ( histname, self.currentFitRange[0] * 10.0, self.useEntryAsData );
|
255 |
else:
|
256 |
out = "%s_fit_%s_from_%1.1f_to_%1.1f_%s" % ( histname, self.currentFitFuntion, self.currentFitRange[0],
|
257 |
self.currentFitRange[1], self.useEntryAsData );
|
258 |
# if self.outputFormat == 'pdf':
|
259 |
# canvas.SaveAs( '%s.eps' % out );
|
260 |
# gROOT.ProcessLine( ".!ps2pdf -dEPSCrop %s.eps" % out );
|
261 |
# gROOT.ProcessLine( ".!rm -f %s.eps" % out );
|
262 |
# else:
|
263 |
canvas.SaveAs( '%s/%s.%s' % ( self.outputFolder, out, self.outputFormat ) )
|
264 |
|
265 |
canvas.Close(); #crucial!
|
266 |
|
267 |
|
268 |
def plotClosureTest( self, histname, results ):
|
269 |
c2 = TCanvas( "c2", "QCD estimates", 1080, 1080 );
|
270 |
x = array( 'd', [2, 3, 4] )
|
271 |
jetBinsOfInterest = [#'1jet',
|
272 |
'2jets', '3jets', '4orMoreJets']
|
273 |
function = self.currentFitFuntion
|
274 |
|
275 |
gStyle.SetMarkerSize( 1.7 );
|
276 |
gStyle.SetMarkerStyle( 20 );
|
277 |
c2.SetTopMargin( 0.1 );
|
278 |
# c2.SetLeftMargin( 0.12 );
|
279 |
c2.SetRightMargin( 0.35 );
|
280 |
|
281 |
y = {}
|
282 |
for fitRange in self.fitRangesClosureTest:
|
283 |
range = '%1.1f-%1.1f' % fitRange
|
284 |
y[range] = []
|
285 |
for bin in jetBinsOfInterest:
|
286 |
|
287 |
est = results[range][bin]['estimatedNumberOfQCDEvents']
|
288 |
true = results[range][bin]['actualNumberOfQCDEvents']
|
289 |
variation = 0
|
290 |
if not true == 0:
|
291 |
variation = ( est - true ) / true
|
292 |
y[range].append( variation )
|
293 |
nbins = 3
|
294 |
gr1 = TGraph( nbins, x, array( 'd', y['%1.1f-%1.1f' % self.fitRangesClosureTest[0]] ) )
|
295 |
gr2 = TGraph( nbins, x, array( 'd', y['%1.1f-%1.1f' % self.fitRangesClosureTest[1]] ) )
|
296 |
gr3 = TGraph( nbins, x, array( 'd', y['%1.1f-%1.1f' % self.fitRangesClosureTest[2]] ) )
|
297 |
gr4 = TGraph( nbins, x, array( 'd', y['%1.1f-%1.1f' % self.fitRangesClosureTest[3]] ) )
|
298 |
gr5 = TGraph( nbins, x, array( 'd', y['%1.1f-%1.1f' % self.fitRangesClosureTest[4]] ) )
|
299 |
gr6 = TGraph( nbins, x, array( 'd', y['%1.1f-%1.1f' % self.fitRangesClosureTest[5]] ) )
|
300 |
gr7 = TGraph( nbins, x, array( 'd', y['%1.1f-%1.1f' % self.fitRangesClosureTest[6]] ) )
|
301 |
gr8 = TGraph( nbins, x, array( 'd', y['%1.1f-%1.1f' % self.fitRangesClosureTest[7]] ) )
|
302 |
gr9 = TGraph( nbins, x, array( 'd', y['%1.1f-%1.1f' % self.fitRangesClosureTest[8]] ) )
|
303 |
|
304 |
gr1.SetMarkerColor( kGreen + 1 );
|
305 |
gr2.SetMarkerColor( kGreen + 2 );
|
306 |
gr3.SetMarkerColor( kGreen + 3 );
|
307 |
gr4.SetMarkerColor( kAzure + 7 );
|
308 |
gr5.SetMarkerColor( kAzure - 3 );
|
309 |
gr6.SetMarkerColor( kBlue );
|
310 |
gr7.SetMarkerColor( kOrange );
|
311 |
gr8.SetMarkerColor( kOrange - 1 );
|
312 |
gr9.SetMarkerColor( kOrange - 6 );
|
313 |
|
314 |
gStyle.SetTitleW( 0.9 );
|
315 |
gStyle.SetTitleH( 0.05 )
|
316 |
|
317 |
h = None
|
318 |
if function == "gaus":
|
319 |
h = TH1D( "h", "Variation of QCD estimates with fit range (Gaussian)", 4, 0.5, 4.5 );
|
320 |
elif function == "pol3":
|
321 |
h = TH1D( "h", "Variation of QCD estimates with fit range (Pol3)", 4, 0.5, 4.5 );
|
322 |
elif function == "pol1":
|
323 |
h = TH1D( "h", "Variation of QCD estimates with fit range (Pol1)", 4, 0.5, 4.5 );
|
324 |
elif function == "landau":
|
325 |
h = TH1D( "h", "Variation of QCD estimates with fit range (Landau)", 4, 0.5, 4.5 );
|
326 |
|
327 |
h.SetStats( kFALSE ); # no statistics
|
328 |
h.Draw();
|
329 |
h.SetYTitle( "Deviation = (N_{QCD,est}-N_{QCD,true})/N_{QCD,true}" );
|
330 |
h.GetYaxis().SetRangeUser( -1, 1 );
|
331 |
h.GetXaxis().SetRangeUser( 1.5, 5.5 );
|
332 |
# h.GetXaxis().SetBinLabel( 1, "1j" );
|
333 |
h.GetXaxis().SetBinLabel( 2, "2j" );
|
334 |
h.GetXaxis().SetBinLabel( 3, "3j" );
|
335 |
h.GetXaxis().SetBinLabel( 4, "#geq4j" );
|
336 |
h.GetXaxis().SetLabelSize( 0.07 );
|
337 |
h.GetYaxis().SetTitleOffset( 1.3 );
|
338 |
|
339 |
gr1.Draw( "P" );
|
340 |
gr2.Draw( "P" ); #to superimpose graphs, do not re-draw axis
|
341 |
gr3.Draw( "P" );
|
342 |
gr4.Draw( "P" );
|
343 |
gr5.Draw( "P" );
|
344 |
gr6.Draw( "P" );
|
345 |
gr7.Draw( "P" );
|
346 |
gr8.Draw( "P" );
|
347 |
gr9.Draw( "P" );
|
348 |
|
349 |
c2.SetGrid( 1, 1 );
|
350 |
|
351 |
leg = TLegend( 0.65, 0.1, 0.98, 0.9 );
|
352 |
leg.SetFillColor( 0 );
|
353 |
leg.AddEntry( gr1, "Free: 0.1-0.9", "p" );
|
354 |
leg.AddEntry( gr2, "Free: 0.1-1.0", "p" );
|
355 |
leg.AddEntry( gr3, "Free: 0.1-1.1", "p" );
|
356 |
leg.AddEntry( gr4, "Free: 0.2-0.9", "p" );
|
357 |
leg.AddEntry( gr5, "Free: 0.2-1.0", "p" );
|
358 |
leg.AddEntry( gr6, "Free: 0.2-1.1", "p" );
|
359 |
leg.AddEntry( gr7, "Free: 0.3-0.9", "p" );
|
360 |
leg.AddEntry( gr8, "Free: 0.3-1.0", "p" );
|
361 |
leg.AddEntry( gr9, "Free: 0.3-1.1", "p" );
|
362 |
|
363 |
leg.Draw();
|
364 |
|
365 |
c2.SaveAs( "%s/%s_qcd_estimate_%s.%s" % ( self.outputFolder, histname, function, self.outputFormat ) )
|
366 |
|
367 |
setRange = h.GetYaxis().SetRangeUser
|
368 |
saveAs = c2.SaveAs
|
369 |
for limit in [1, 2, 3, 6, 8]:
|
370 |
setRange( -limit, limit );
|
371 |
saveAs( "%s/%s_qcd_estimate_%s_zoom_%d.%s" % ( self.outputFolder, histname, function, limit, self.outputFormat ) );
|
372 |
|
373 |
def getFitParameters( self, fitFunction ):
|
374 |
fitParameters = {'chi2':-1, 'numberOfdegreesOfFreedom': 0, 'constrain1': 0, 'constrain2': 0,
|
375 |
'constrain3': 0, 'constrain4': 0}
|
376 |
if fitFunction:
|
377 |
fitParameters['chi2'] = fitFunction.GetChisquare()
|
378 |
fitParameters['numberOfdegreesOfFreedom'] = fitFunction.GetNDF()
|
379 |
return fitParameters
|
380 |
|
381 |
def doConstrainedFit( self, histogram, function = 'gaus', limits = ( 0.1, 1.6 ) ):
|
382 |
fitFunction = None
|
383 |
if function == 'gaus':
|
384 |
fitFunction = TF1( "gaus", "gaus", 0, 2 );
|
385 |
elif function == 'pol3':
|
386 |
fitFunction = TF1( "pol3", "[0] * ( 1 + [1]*x + [2]*x^2 + [3]*x^3 )", 0, 2 );
|
387 |
elif function == 'landau':
|
388 |
fitFunction = TF1( "landau", "landau", 0, 2 )
|
389 |
|
390 |
|
391 |
myFitResult = data.Fit( function, "Q0", "ah", limits[0], limits[1] );
|
392 |
|
393 |
def add_cms_label( self, njet = "" ):
|
394 |
|
395 |
mytext = TPaveText( 0.3, 0.8, 0.6, 0.93, "NDC" );
|
396 |
mytext.AddText( "CMS Preliminary" );
|
397 |
mytext.AddText( "%.1f pb^{-1} at #sqrt{s} = 7 TeV" % self.luminosity );
|
398 |
if njet != "":
|
399 |
mytext.AddText( "e+jets, %s" % self.jetBinsLatex[njet] )
|
400 |
mytext.SetFillStyle( 0 );
|
401 |
mytext.SetBorderSize( 0 );
|
402 |
mytext.SetTextFont( 42 );
|
403 |
mytext.SetTextAlign( 13 );
|
404 |
return mytext
|
405 |
|
406 |
def add_legend( self, histname ):
|
407 |
function = self.currentFitFuntion
|
408 |
|
409 |
tt = self.histograms['ttbar'][histname]
|
410 |
wj = self.histograms['wjets'][histname]
|
411 |
zj = self.histograms['zjets'][histname]
|
412 |
data = self.histograms['data'][histname]
|
413 |
QCD = self.histograms['qcd'][histname]
|
414 |
stop = self.histograms['singleTop'][histname]
|
415 |
|
416 |
leg = TLegend( 0.64, 0.4, 0.9, 0.9 );
|
417 |
leg.SetFillStyle( 0 );
|
418 |
leg.SetBorderSize( 0 );
|
419 |
leg.SetTextFont( 42 );
|
420 |
|
421 |
# Here I define coloured lines for use in the legend
|
422 |
blue = TF1( "blue", "pol0", 0, 1 );
|
423 |
red = TF1( "red", "pol0", 0, 1 );
|
424 |
|
425 |
blue.SetLineColor( kBlue );
|
426 |
red.SetLineColor( kRed );
|
427 |
|
428 |
red.SetLineWidth( 2 );
|
429 |
blue.SetLineWidth( 2 );
|
430 |
|
431 |
blue.SetLineStyle( kDashed );
|
432 |
|
433 |
# Add entry to legend
|
434 |
if self.useEntryAsData == 'data':
|
435 |
leg.AddEntry( data, "Data", "LP" );
|
436 |
else:
|
437 |
leg.AddEntry( data, "All MC events", "LP" );
|
438 |
if function == "pol1":
|
439 |
leg.AddEntry( red, "Linear Fit", "l" );
|
440 |
elif function == "expo":
|
441 |
leg.AddEntry( red, "Exponenetial Fit", "l" );
|
442 |
elif function == "gaus":
|
443 |
leg.AddEntry( red, "Gaussian Fit", "l" );
|
444 |
|
445 |
leg.AddEntry( blue, "Extrapolation", "l" );
|
446 |
leg.AddEntry( tt, "t#bar{t}", "F" );
|
447 |
leg.AddEntry( stop, "Single-Top", "F" );
|
448 |
leg.AddEntry( wj, "W#rightarrowl#nu", "F" );
|
449 |
leg.AddEntry( zj, "Z/#gamma*#rightarrowl^{+}l^{-}", "F" );
|
450 |
leg.AddEntry( QCD, "QCD & #gamma+jets", "F" );
|
451 |
leg.Draw()
|
452 |
return ( leg, red, blue )
|
453 |
|
454 |
def printResults( self, results ):
|
455 |
self.printJetBinResults( results, '3jets' )
|
456 |
print '=' * 60
|
457 |
self.printJetBinResults( results, '3orMoreJets' )
|
458 |
print '=' * 60
|
459 |
self.printJetBinResults( results, '4orMoreJets' )
|
460 |
print '=' * 60
|
461 |
|
462 |
|
463 |
def printJetBinResults( self, results, jetBin ):
|
464 |
estimate = 0
|
465 |
estimate2 = 0
|
466 |
predicted = results[results.keys()[0]][jetBin]['actualNumberOfQCDEvents']
|
467 |
allData = results[results.keys()[0]][jetBin]['numberOfAllDataEvents']
|
468 |
allMC = results[results.keys()[0]][jetBin]['numberOfAllMCEvents']
|
469 |
|
470 |
if jetBin == '4orMoreJets':
|
471 |
print 'Estimation for >= 4 jets'
|
472 |
elif jetBin == '3orMoreJets':
|
473 |
print 'Estimation for >= 3 jets'
|
474 |
elif jetBin == '3jets':
|
475 |
print 'Estimation for == 3 jets'
|
476 |
print 'predicted number of QCD events', predicted
|
477 |
for fitRange in self.fitRangesEstimation:
|
478 |
range = '%1.1f-%1.1f' % fitRange
|
479 |
est = results[range][jetBin]['estimatedNumberOfQCDEvents']
|
480 |
true = results[range][jetBin]['actualNumberOfQCDEvents']
|
481 |
variation = ( est - true ) / true
|
482 |
estimate += est
|
483 |
estimate2 += est * est
|
484 |
|
485 |
|
486 |
print
|
487 |
print 'estimated number of QCD events'
|
488 |
print 'for range', range, ': ',
|
489 |
print est
|
490 |
print
|
491 |
mean = estimate / len( self.fitRangesEstimation )
|
492 |
mean2 = estimate2 / len( self.fitRangesEstimation )
|
493 |
error = sqrt( ( mean2 - mean * mean ) / len( self.fitRangesEstimation ) )
|
494 |
print 'average estimate', mean, '+-', error
|
495 |
weight = estimate / len( self.fitRangesEstimation ) / predicted
|
496 |
print 'average weight factor', weight
|
497 |
print 'Total number of data in signal bin(<0.1)', allData
|
498 |
print 'Total number of MC in signal bin(<0.1) before reweighting QCD', allMC
|
499 |
print 'Total number of MC in signal bin(<0.1) after reweighting QCD', ( allMC - predicted ) + predicted * weight
|
500 |
|
501 |
def plotControlRegionComparison( self ):
|
502 |
for bin in self.jetBins:
|
503 |
hist = self.pfIsoHistogramPrefix + bin
|
504 |
histControl = self.pfIsoControlRegionHistogramPrefix + bin
|
505 |
QCD_control = self.histograms['qcd'][histControl]
|
506 |
QCD = self.histograms['qcd'][hist]
|
507 |
nQCD_Control = QCD_control.Integral()
|
508 |
nQCD = QCD.Integral()
|
509 |
if nQCD_Control > 0:
|
510 |
QCD_control.Scale( 1 / nQCD_Control )
|
511 |
if nQCD > 0:
|
512 |
QCD.Scale( 1 / nQCD )
|
513 |
QCD_control.SetFillStyle( 3004 )
|
514 |
QCD.GetXaxis().SetRangeUser( 0., self.maxValue - 0.01 )
|
515 |
|
516 |
max = 0
|
517 |
if QCD.GetMaximum() > QCD_control.GetMaximum():
|
518 |
max = QCD.GetMaximum()*1.1
|
519 |
else:
|
520 |
max = QCD_control.GetMaximum()*1.1
|
521 |
|
522 |
QCD.GetYaxis().SetRangeUser( 0., max )
|
523 |
|
524 |
canvas = TCanvas( "c1", "Shape comparision", 1920, 1080 )
|
525 |
QCD.Draw()
|
526 |
QCD_control.Draw( 'same' )
|
527 |
label = self.add_cms_label( bin )
|
528 |
label.Draw()
|
529 |
|
530 |
leg = TLegend( 0.64, 0.4, 0.9, 0.9 );
|
531 |
leg.SetFillStyle( 0 );
|
532 |
leg.SetBorderSize( 0 );
|
533 |
leg.SetTextFont( 42 );
|
534 |
leg.AddEntry( QCD_control, 'QCD control region' )
|
535 |
leg.AddEntry( QCD, 'QCD standard selection' )
|
536 |
leg.Draw()
|
537 |
|
538 |
canvas.SaveAs( '%s/%s_shapeComparison.%s' % ( self.outputFolder, hist, self.outputFormat ) )
|
539 |
|
540 |
if __name__ == '__main__':
|
541 |
gROOT.SetBatch( True )
|
542 |
gROOT.ProcessLine( 'gErrorIgnoreLevel = 1001;' )
|
543 |
|
544 |
path = '/storage/results/outputfiles/Preapproval2/'
|
545 |
files = {'data': path + "data_36.145pb_PFElectron_PF2PATJets_PFMET.root",
|
546 |
'ttbar' : path + "ttjet_36.145pb_PFElectron_PF2PATJets_PFMET.root",
|
547 |
'wjets' : path + "wj_36.145pb_PFElectron_PF2PATJets_PFMET.root",
|
548 |
'zjets' : path + "zj_36.145pb_PFElectron_PF2PATJets_PFMET.root",
|
549 |
'bce1' : path + "bce1_36.145pb_PFElectron_PF2PATJets_PFMET.root",
|
550 |
'bce2' : path + "bce2_36.145pb_PFElectron_PF2PATJets_PFMET.root",
|
551 |
'bce3' : path + "bce3_36.145pb_PFElectron_PF2PATJets_PFMET.root",
|
552 |
'enri1' : path + "enri1_36.145pb_PFElectron_PF2PATJets_PFMET.root",
|
553 |
'enri2' : path + "enri2_36.145pb_PFElectron_PF2PATJets_PFMET.root",
|
554 |
'enri3' : path + "enri3_36.145pb_PFElectron_PF2PATJets_PFMET.root",
|
555 |
'pj1' : path + "pj1_36.145pb_PFElectron_PF2PATJets_PFMET.root",
|
556 |
'pj2' : path + "pj2_36.145pb_PFElectron_PF2PATJets_PFMET.root",
|
557 |
'pj3' : path + "pj3_36.145pb_PFElectron_PF2PATJets_PFMET.root",
|
558 |
'tW' : path + "tW_36.145pb_PFElectron_PF2PATJets_PFMET.root",
|
559 |
'tchan' : path + "tchan_36.145pb_PFElectron_PF2PATJets_PFMET.root"}
|
560 |
q = QCDEstimator( files )
|
561 |
QCDEstimator.outputFolder = '/storage/results/QCD_Estimate/Preapproval2'
|
562 |
QCDEstimator.outputFormat = 'pdf'
|
563 |
|
564 |
q.doEstimate( 'gaus' )
|
565 |
print '=' * 60
|
566 |
print 'ParticleFlowIsolation results'
|
567 |
q.printResults( q.allPfIsoResults )
|
568 |
# print 'Relative isolation results'
|
569 |
# q.printResults( q.allRelIsoResults )
|
570 |
# print '=' * 60
|
571 |
|
572 |
|
573 |
print 'Starting closure tests'
|
574 |
q.doClosureTests( 'gaus' )
|
575 |
q.plotControlRegionComparison()
|
576 |
|