9 from optparse
import OptionParser
12 __author__ =
"Mauro Verzetti (mauro.verzetti@cern.ch)"
13 __doc__ =
"""Script to plot the content of a Validation .root file and compare it to a different file:\n\n
14 Usage: MultipleCompare.py -T testFile -R refFile [options] [search strings that you want to apply '*' is supported as special character]"""
18 parser = OptionParser(description=__doc__)
19 parser.add_option(
'--myhelp',metavar=
'', action=
"store_true",help=
'prints this output message',dest=
'help',default =
False)
20 parser.add_option(
'--TestFile',
'-T',metavar=
'testFile', type=str,help=
'Sets the test file',dest=
'test',default =
'')
21 parser.add_option(
'--RefFile',
'-R',metavar=
'refFile', type=str,help=
'Sets the reference file',dest=
'ref',default =
None)
22 parser.add_option(
'--output',
'-o',metavar=
'outputFile', type=str,help=
'Sets the output file',dest=
'out',default =
'MultipleCompare.png')
23 parser.add_option(
'--logScale',action=
"store_true", dest=
"logScale", default=
False, help=
"Sets the log scale in the plot")
24 parser.add_option(
'--fakeRate',
'-f',action=
"store_true", dest=
"fakeRate", default=
False, help=
"Sets the fake rate options and put the correct label (implies --logScale)")
25 parser.add_option(
'--testLabel',
'-t',metavar=
'testLabel', type=str,help=
'Sets the label to put in the plots for test file',dest=
'testLabel',default =
None)
26 parser.add_option(
'--refLabel',
'-r',metavar=
'refLabel', type=str,help=
'Sets the label to put in the plots for ref file',dest=
'refLabel',default =
None)
27 parser.add_option(
'--maxLog',metavar=
'number', type=float,help=
'Sets the maximum of the scale in log scale (requires --logScale or -f to work)',dest=
'maxLog',default = 3)
28 parser.add_option(
'--minDiv',metavar=
'number', type=float,help=
'Sets the minimum of the scale in the ratio pad',dest=
'minDiv',default = 0.001)
29 parser.add_option(
'--maxDiv',metavar=
'number', type=float,help=
'Sets the maximum of the scale in the ratio pad',dest=
'maxDiv',default = 2)
30 parser.add_option(
'--logDiv',action=
"store_true", dest=
"logDiv", default=
False, help=
"Sets the log scale in the plot")
31 parser.add_option(
'--normalize',action=
"store_true", dest=
"normalize", default=
False, help=
"plot normalized")
32 parser.add_option(
'--maxRange',metavar=
'number',type=float, dest=
"maxRange", default=1.6, help=
"Sets the maximum range in linear plots")
33 parser.add_option(
'--rebin', dest=
"rebin", type=int, default=-1, help=
"Sets the rebinning scale")
34 parser.add_option(
'--branding',
'-b',metavar=
'branding', type=str,help=
'Define a branding to label the plots (in the top right corner)',dest=
'branding',default =
None)
37 (options,toPlot) = parser.parse_args()
41 return [options, toPlot]
44 tempList = dir.GetListOfKeys()
46 for it
in range(0,tempList.GetSize()):
47 retList.append(tempList.At(it).ReadObj())
52 for entry
in dirContent:
53 if type(entry)
is TDirectory
or type(entry)
is TDirectoryFile:
54 subdirName = os.path.join(dirName,entry.GetName())
57 pathname = os.path.join(dirName,entry.GetName())
58 objectList.append(pathname)
61 for part
in required.split(
'*'):
62 if got.find(part) == -1:
67 ret = hNum.Clone(
'Division')
68 ret.GetYaxis().SetTitle(
'Ratio')
69 for binI
in range(hNum.GetNbinsX()):
70 denVal = hDen.GetBinContent(binI)
71 denErr = hDen.GetBinError(binI)
72 numErr = hNum.GetBinError(binI)
73 numVal = hNum.GetBinContent(binI)
75 ret.SetBinContent(binI,0)
76 ret.SetBinError(binI,0)
78 ret.SetBinContent(binI,numVal/denVal)
80 ret.SetBinError(binI,1)
82 ret.SetBinError(binI,(numVal/denVal)*math.sqrt(math.pow(numErr/numVal,2) + math.pow(denErr/denVal,2) ) )
91 matches = re.match(
r'.*/(.*)_(.*)_(.*)', name)
93 prefix = matches.group(1)
94 label = matches.group(3)
95 knowntypes = ([
'pTRatio',
'SumPt',
'Size'])
96 for knowntype
in knowntypes:
97 if matches.group(2) == knowntype:
104 prefixParts = prefix.partition(
'Discrimination')
105 if prefixParts[2] !=
'':
106 prefix = prefixParts[2]
107 prefixParts = prefix.partition(
'By')
108 if prefixParts[2] !=
'':
109 prefix = prefixParts[2]
112 return [type, label, prefix]
117 title.SetTextAlign(12)
118 title.SetTextSize(.035)
119 leftMargin = gStyle.GetPadLeftMargin()
120 topMargin = 1 - 0.5*gStyle.GetPadTopMargin()
121 title.DrawLatex(leftMargin, topMargin, text)
124 if options.branding !=
None or label !=
'':
127 text.SetTextAlign(11)
128 text.SetTextSize(.025)
129 text.SetTextColor(13)
130 if options.out.find(
".eps")!=-1:
131 text.SetTextAngle(-91.0)
133 text.SetTextAngle(-90.0)
134 rightMargin = 1 - gStyle.GetPadRightMargin()
135 topMargin = 1 - gStyle.GetPadTopMargin()
138 text.DrawLatex(rightMargin+.01, topMargin+0.025, label+options.branding);
142 root = histoPath[:histoPath.find(
'_')]
143 par = histoPath[histoPath.find(
'Eff')+3:]
144 validationPlots = validation.proc.efficiencies.plots._Parameterizable__parameterNames
148 for efficiency
in validationPlots:
149 effpset = getattr(validation.proc.efficiencies.plots,efficiency)
150 effName = effpset.efficiency.value()
151 effNameCut = effName[effName.find(
'_'):effName.find(
'#')]
152 if effNameCut
in histoPath:
154 print 'More than one pair of parents found for ' + histopath +
':'
156 num = root + effpset.numerator.value()[effName.find(
'_'):].
replace(
'#PAR#',par)
157 den = root + effpset.denominator.value()[effName.find(
'_'):].
replace(
'#PAR#',par)
161 def Rebin(tfile, histoPath, rebinVal):
163 num = tfile.Get(parents[0])
164 if type(num) != TH1F:
165 print 'Looking for '+num
166 print 'Plot now found! What the hell are you doing? Exiting...'
168 denSingle = tfile.Get(parents[1])
169 if type(denSingle) != TH1F:
170 print 'Looking for '+denSingle
171 print 'Plot now found! What the hell are you doing? Exiting...'
174 den = denSingle.Rebin(rebinVal,
'denClone')
175 retVal = num.Clone(histoPath+
'Rebin%s'%rebinVal)
179 retVal.Divide(num,den,1,1,
'B')
188 if min0 == -1
or max0 == -1:
193 if minTmp < min
or min == -1:
197 if maxTmp > max
or max == -1:
203 if pad.GetLogy()
and argv.count(
'maxLog') > 0:
204 maxLog = options.maxLog
216 if max <= 1.1
and max > 0.7:
218 hists[0].SetAxisRange(min, max,
"Y")
223 if argv.count(
'minDiv') > 0:
225 if argv.count(
'maxDiv') > 0:
230 hists[0].SetAxisRange(min, max,
"Y")
238 for i
in range(1, hist.GetNbinsX()):
239 if hist.GetBinContent(i) > max:
240 max = hist.GetBinContent(i)
242 return max + distance*hist.GetBinError(pos)
250 for i
in range(1, hist.GetNbinsX()):
251 if hist.GetBinContent(i)<=0.:
253 if hist.GetBinContent(i) < min
or min==-1:
254 min = hist.GetBinContent(i)
258 return min - distance*hist.GetBinError(pos)
267 gROOT.SetStyle(
'Plain')
271 gStyle.SetPadGridX(
True)
272 gStyle.SetPadGridY(
True)
273 gStyle.SetOptTitle(0)
274 gStyle.SetPadTopMargin(0.1)
275 gStyle.SetPadBottomMargin(0.1)
276 gStyle.SetPadLeftMargin(0.13)
277 gStyle.SetPadRightMargin(0.07)
280 testFile = TFile(options.test)
282 if options.ref !=
None:
283 refFile = TFile(options.ref)
291 for path
in plotList:
292 if Match(plot.lower(),path.lower()):
293 histoList.append(path)
300 print '\tError: Please specify at least one histogram.'
302 print 'Check your plot list:', toPlot
310 scaleToIntegral =
False
311 if options.normalize:
312 scaleToIntegral =
True
314 ylabel =
'Efficiency'
320 if histType==
'pTRatio' and len(histoList)<3:
325 x2 = 1-gStyle.GetPadRightMargin()
326 y2 = 1-gStyle.GetPadTopMargin()
328 if len(histoList) == 1:
330 y1 = y2 - lineHeight*len(histoList)
331 legend = TLegend(x1,y1,x2,y2)
333 legend.SetFillColor(0)
336 y1 = y2 - .07*len(histoList)
337 statsBox = TPaveText(x1,y1,x2,y2,
"NDC")
338 statsBox.SetFillColor(0)
339 statsBox.SetTextAlign(12)
340 statsBox.SetMargin(0.05)
341 statsBox.SetBorderSize(1)
344 canvas = TCanvas(
'MultiPlot',
'MultiPlot',validation.standardDrawingStuff.canvasSizeX.value(),832)
345 effPad = TPad(
'effPad',
'effPad',0,0.25,1.,1.,0,0)
346 effPad.SetBottomMargin(0.1);
347 effPad.SetTopMargin(0.1);
348 effPad.SetLeftMargin(0.13);
349 effPad.SetRightMargin(0.07);
352 if options.testLabel !=
None:
353 header +=
'Dots: '+options.testLabel
354 if options.refLabel !=
None:
355 header +=
' Line: '+options.refLabel
358 diffPad = TPad(
'diffPad',
'diffPad',0.,0.,1,.25,0,0)
360 colors = [2,3,4,6,5,7,28,1,2,3,4,6,5,7,28,1,2,3,4,6,5,7,28,1,2,3,4,6,5,7,28,1,2,3,4,6,5,7,28,1]
363 statTemplate =
'%s Mean: %.3f RMS: %.3f'
366 for histoPath,color
in zip(histoList,colors):
367 if(options.rebin == -1):
368 testH = testFile.Get(histoPath)
370 testH =
Rebin(testFile,histoPath,options.rebin)
371 if type(testH) != TH1F:
372 print 'Looking for '+histoPath
373 print 'Test plot now found! What the hell are you doing? Exiting...'
376 xAx = histoPath[histoPath.find(
'Eff')+len(
'Eff'):]
378 if not testH.GetXaxis().GetTitle():
379 if hasattr(validation.standardDrawingStuff.xAxes,xAx):
380 testH.GetXaxis().SetTitle( getattr(validation.standardDrawingStuff.xAxes,xAx).xAxisTitle.value())
381 if not testH.GetYaxis().GetTitle():
382 testH.GetYaxis().SetTitle(ylabel)
384 testH.GetXaxis().SetTitle(label+
': '+testH.GetXaxis().GetTitle())
385 testH.GetXaxis().SetTitleOffset(1.1)
386 testH.GetYaxis().SetTitleOffset(1.5)
387 testH.SetMarkerSize(1)
388 testH.SetMarkerStyle(20)
389 testH.SetMarkerColor(color)
390 if histType ==
'Eff':
391 legend.AddEntry(testH,histoPath[histoPath.rfind(
'/')+1:histoPath.find(histType)],
'p')
395 text = statsBox.AddText(statTemplate % (
'Dots',testH.GetMean(), testH.GetRMS()) )
396 text.SetTextColor(color)
402 if testH.GetEntries() > 0:
403 if not testH.GetSumw2N():
405 testH.DrawNormalized(
'ex0 P')
407 print "--> Warning! You tried to normalize a histogram which seems to be already scaled properly. Draw it unscaled."
408 scaleToIntegral =
False
414 if testH.GetEntries() > 0:
415 testH.DrawNormalized(
'same p')
417 testH.Draw(
'same ex0 l')
420 if(options.rebin == -1):
421 refH = refFile.Get(histoPath)
423 refH =
Rebin(refFile,histoPath,options.rebin)
424 if type(refH) != TH1F:
427 refH.SetLineColor(color)
430 if testH.GetEntries() > 0:
431 refH.DrawNormalized(
'same hist')
433 refH.DrawCopy(
'same hist')
435 text = statsBox.AddText(statTemplate % (
'Line',refH.GetMean(), refH.GetRMS()) )
436 text.SetTextColor(color)
437 refH.SetFillColor(color)
438 refH.SetFillStyle(3001)
440 entries = testH.GetEntries()
442 testH.Scale(1./entries)
443 entries = refH.GetEntries()
446 refH.Scale(1./entries)
448 divHistos.append(
Divide(testH,refH))
451 tmpHists.extend(testHs)
452 tmpHists.extend(refHs)
457 for histo,color
in zip(divHistos,colors):
459 histo.SetMarkerSize(1)
460 histo.SetMarkerStyle(20)
461 histo.SetMarkerColor(color)
462 histo.GetYaxis().SetLabelSize(0.08)
463 histo.GetYaxis().SetTitleOffset(0.6)
464 histo.GetYaxis().SetTitleSize(0.08)
465 histo.GetXaxis().SetLabelSize(0.)
466 histo.GetXaxis().SetTitleSize(0.)
473 histo.Draw(
'same ex0')
481 canvas.Print(options.out)
484 if __name__ ==
'__main__':
def getMaximumIncludingErrors
def LoadCommandlineOptions
def getMinimumIncludingErrors