1 |
dhidas |
1.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 |
|
|
|