9 from optparse
import OptionParser
12 __author__ =
"Mauro Verzetti (mauro.verzetti@cern.ch) and Lucia Perrini (lucia.perrini@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(
'--logScaleY',action=
"store_true", dest=
"logScaleY", default=
False, help=
"Sets the log scale in the plot (Y axis)")
24 parser.add_option(
'--logScaleX',action=
"store_true", dest=
"logScaleX", default=
False, help=
"Sets the log scale in the plot (X axis)")
25 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)")
26 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)
27 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)
28 parser.add_option(
'--sampleLabel',
'-s',metavar=
'sampleLabel', type=str,help=
'Sets the label to indicate the sample used',dest=
'sampleLabel',default =
None)
29 parser.add_option(
'--maxLogX',metavar=
'number', type=float,help=
'Sets the maximum of the scale in log scale both in the main and in the sub pad (requires --logScale or -f to work)',dest=
'maxLogX',default = 100)
30 parser.add_option(
'--minLogX',metavar=
'number', type=float,help=
'Sets the minimum of the scale in log scale (requires --logScale or -f to work)',dest=
'minLogX',default = 0.001)
31 parser.add_option(
'--minLogY',metavar=
'number', type=float,help=
'Sets the minimum of the scale in log scale (requires --logScale or -f to work)',dest=
'minLogY',default = 0.0001)
32 parser.add_option(
'--maxLogY',metavar=
'number', type=float,help=
'Sets the maximum of the scale in log scale (requires --logScale or -f to work)',dest=
'maxLogY',default = 3)
33 parser.add_option(
'--minYR',metavar=
'number', type=float,help=
'Sets the minimum of the scale in sub pad',dest=
'minYR',default = 0)
34 parser.add_option(
'--maxYR',metavar=
'number', type=float,help=
'Sets the maximum of the scale in sub pad',dest=
'maxYR',default = 1.2)
39 parser.add_option(
'--logDiv',action=
"store_true", dest=
"logDiv", default=
False, help=
"Sets the log scale in the plot")
40 parser.add_option(
'--normalize',action=
"store_true", dest=
"normalize", default=
False, help=
"plot normalized")
41 parser.add_option(
'--maxRange',metavar=
'number',type=float, dest=
"maxRange", default=1.6, help=
"Sets the maximum range in linear plots")
42 parser.add_option(
'--maxXaxis',metavar=
'number',type=float, dest=
"maxXaxis", default=800, help=
"Sets the maximum range on x axis in the main pad")
43 parser.add_option(
'--minXaxis',metavar=
'number',type=float,help=
"Sets the minimum range on x axis in the main pad",dest=
"minXaxis", default=-3)
44 parser.add_option(
'--maxYaxis',metavar=
'number',type=float, dest=
"maxYaxis", default=2, help=
"Sets the maximum range on Y axis in the main pad")
45 parser.add_option(
'--minYaxis',metavar=
'number',type=float, dest=
"minYaxis", default=0, help=
"Sets the minimum range on Y axis in the main pad")
46 parser.add_option(
'--rebin', dest=
"rebin", type=int, default=-1, help=
"Sets the rebinning scale")
47 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)
50 (options,toPlot) = parser.parse_args()
54 return [options, toPlot]
57 tempList = dir.GetListOfKeys()
59 for it
in range(0,tempList.GetSize()):
60 retList.append(tempList.At(it).ReadObj())
65 for entry
in dirContent:
66 if type(entry)
is TDirectory
or type(entry)
is TDirectoryFile:
67 subdirName = os.path.join(dirName,entry.GetName())
70 pathname = os.path.join(dirName,entry.GetName())
71 objectList.append(pathname)
74 for part
in required.split(
'*'):
75 if got.find(part) == -1:
80 ret = hNum.Clone(
'Division')
81 ret.GetYaxis().SetTitle(
'Ratio')
82 for binI
in range(hNum.GetNbinsX()+1):
83 denVal = hDen.GetBinContent(binI)
84 denErr = hDen.GetBinError(binI)
85 numErr = hNum.GetBinError(binI)
86 numVal = hNum.GetBinContent(binI)
88 ret.SetBinContent(binI,0)
89 ret.SetBinError(binI,0)
91 ret.SetBinContent(binI,numVal/denVal)
93 ret.SetBinError(binI,1)
95 ret.SetBinError(binI,(numVal/denVal)*math.sqrt(math.pow(numErr/numVal,2) + math.pow(denErr/denVal,2) ) )
104 matches = re.match(
r'.*/(.*)_(.*)_(.*)', name)
106 prefix = matches.group(1)
107 label = matches.group(3)
108 knowntypes = ([
'pTRatio',
'SumPt',
'Size'])
109 for knowntype
in knowntypes:
110 if matches.group(2) == knowntype:
117 prefixParts = prefix.partition(
'Discrimination')
118 if prefixParts[2] !=
'':
119 prefix = prefixParts[2]
120 prefixParts = prefix.partition(
'By')
121 if prefixParts[2] !=
'':
122 prefix = prefixParts[2]
125 return [type, label, prefix]
130 title.SetTextAlign(12)
131 title.SetTextSize(.035)
132 leftMargin = gStyle.GetPadLeftMargin()
133 topMargin = 1 - 0.5*gStyle.GetPadTopMargin()
134 title.DrawLatex(leftMargin, topMargin, text)
137 if options.branding !=
None or label !=
'':
140 text.SetTextAlign(11)
141 text.SetTextSize(.025)
142 text.SetTextColor(13)
143 if options.out.find(
".eps")!=-1:
144 text.SetTextAngle(-91.0)
146 text.SetTextAngle(-90.0)
147 rightMargin = 1 - gStyle.GetPadRightMargin()
148 topMargin = 1 - gStyle.GetPadTopMargin()
151 text.DrawLatex(rightMargin+.01, topMargin+0.025, label+options.branding);
155 root = histoPath[:histoPath.find(
'_')]
156 par = histoPath[histoPath.find(
'Eff')+3:]
157 validationPlots = validation.proc.efficiencies.plots._Parameterizable__parameterNames
161 for efficiency
in validationPlots:
162 effpset = getattr(validation.proc.efficiencies.plots,efficiency)
163 effName = effpset.efficiency.value()
164 effNameCut = effName[effName.find(
'_'):effName.find(
'#')]
165 if effNameCut
in histoPath:
167 print 'More than one pair of parents found for ' + histopath +
':'
169 num = root + effpset.numerator.value()[effName.find(
'_'):].
replace(
'#PAR#',par)
170 den = root + effpset.denominator.value()[effName.find(
'_'):].
replace(
'#PAR#',par)
174 def Rebin(tfile, histoPath, rebinVal):
176 num = tfile.Get(parents[0])
177 if type(num) != TH1F:
178 print 'Looking for ' + num
179 print 'Plot now found! What the hell are you doing? Exiting...'
181 denSingle = tfile.Get(parents[1])
182 if type(denSingle) != TH1F:
183 print 'Looking for '+denSingle
184 print 'Plot now found! What the hell are you doing? Exiting...'
187 den = denSingle.Rebin(rebinVal,
'denClone')
188 retVal = num.Clone(histoPath+
'Rebin%s'%rebinVal)
192 retVal.Divide(num,den,1,1,
'B')
201 if min0 == -1
or max0 == -1:
206 if minTmp < min
or min == -1:
210 if maxTmp > max
or max == -1:
221 minY, maxY =
findRange(hists, -1, maxLogY)
223 minY, maxY =
findRange(hists, minY_, maxY_)
231 if maxY <= 1.1
and maxY > 0.7:
233 hists[0].SetAxisRange(minY, maxY,
"Y")
240 minX, maxX =
findRange(hists, -1, maxLogX)
242 minX, maxX =
findRange(hists, minX_, maxX_)
250 if maxX <= 1.1
and maxX > 0.7:
252 hists[0].SetAxisRange(minX, maxX,
"X")
261 minX, maxX =
findRange(hists, -1, maxLogX)
263 minX, maxX =
findRange(hists, minX_, maxX_)
270 if maxX <= 1.1
and maxX > 0.7:
272 hists[0].SetAxisRange(minX, maxX,
"X")
283 hists[0].SetAxisRange(min, max,
"Y")
290 for i
in range(1, hist.GetNbinsX()):
291 if hist.GetBinContent(i) > max:
292 max = hist.GetBinContent(i)
294 return max + distance*hist.GetBinError(pos)
302 for i
in range(1, hist.GetNbinsX()):
303 if hist.GetBinContent(i)<=0.:
305 if hist.GetBinContent(i) < min
or min==-1:
306 min = hist.GetBinContent(i)
310 return min - distance*hist.GetBinError(pos)
319 gROOT.SetStyle(
'Plain')
323 gStyle.SetPadGridX(
True)
324 gStyle.SetPadGridY(
True)
325 gStyle.SetOptTitle(0)
326 gStyle.SetPadTopMargin(0.1)
327 gStyle.SetPadBottomMargin(0.1)
328 gStyle.SetPadLeftMargin(0.13)
329 gStyle.SetPadRightMargin(0.07)
332 testFile = TFile(options.test)
334 if options.ref !=
None:
335 refFile = TFile(options.ref)
343 for path
in plotList:
344 if Match(plot.lower(),path.lower()):
345 histoList.append(path)
352 print '\tError: Please specify at least one histogram.'
354 print 'Check your plot list:', toPlot
362 scaleToIntegral =
False
363 if options.normalize:
364 scaleToIntegral =
True
366 ylabel =
'Efficiency'
372 if histType==
'pTRatio' and len(histoList)<3:
377 x2 = 1-gStyle.GetPadRightMargin()
378 y2 = 1-gStyle.GetPadTopMargin()
380 if len(histoList) == 1:
382 y1 = y2 - lineHeight*len(histoList)
383 legend = TLegend(x1,y1,x2,y2)
384 legend.SetHeader(label)
385 legend.SetFillColor(0)
386 legend.SetTextSize(0.032)
389 y1 = y2 - .07*len(histoList)
390 statsBox = TPaveText(x1,y1,x2,y2,
"NDC")
391 statsBox.SetFillColor(0)
392 statsBox.SetTextAlign(12)
393 statsBox.SetMargin(0.05)
394 statsBox.SetBorderSize(1)
397 canvas = TCanvas(
'MultiPlot',
'MultiPlot',validation.standardDrawingStuff.canvasSizeX.value(),832)
398 effPad = TPad(
'effPad',
'effPad',0.01,0.35,0.99,0.99)
399 effPad.SetBottomMargin(0.0)
405 if options.sampleLabel !=
None:
406 header +=
'Sample: '+options.sampleLabel
407 if options.testLabel !=
None:
408 header +=
' Dots: '+options.testLabel
409 if options.refLabel !=
None:
410 header +=
' Line: '+options.refLabel
413 diffPad = TPad(
'diffPad',
'diffPad',0.01,0.01,0.99,0.32)
414 diffPad.SetTopMargin(0.00);
415 diffPad.SetBottomMargin(0.30);
417 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]
420 statTemplate =
'%s Mean: %.3f RMS: %.3f'
423 for histoPath,color
in zip(histoList,colors):
424 if(options.rebin == -1):
425 testH = testFile.Get(histoPath)
427 testH =
Rebin(testFile,histoPath,options.rebin)
428 if type(testH) != TH1F:
429 print 'Looking for '+histoPath
430 print 'Test plot now found! What the hell are you doing? Exiting...'
433 xAx = histoPath[histoPath.find(
'Eff')+len(
'Eff'):]
435 if not testH.GetXaxis().GetTitle():
436 if hasattr(validation.standardDrawingStuff.xAxes,xAx):
437 testH.GetXaxis().SetTitle( getattr(validation.standardDrawingStuff.xAxes,xAx).xAxisTitle.value())
438 if not testH.GetYaxis().GetTitle():
439 testH.GetYaxis().SetTitle(ylabel)
441 testH.GetXaxis().SetTitle(label+
': '+testH.GetXaxis().GetTitle())
442 testH.GetXaxis().SetTitleOffset(1.1)
443 testH.GetXaxis().SetRangeUser(options.minXaxis,options.maxXaxis)
444 testH.GetYaxis().SetTitleOffset(1.1)
447 testH.SetMarkerSize(1)
448 testH.SetMarkerStyle(20)
449 testH.SetMarkerColor(color)
450 if histType ==
'Eff':
451 legend.AddEntry(testH,histoPath[histoPath.rfind(
'/')+1:histoPath.find(histType)],
'p')
455 text = statsBox.AddText(statTemplate % (
'Dots',testH.GetMean(), testH.GetRMS()) )
456 text.SetTextColor(color)
459 if options.logScaleY:
461 if options.logScaleX:
465 if testH.GetEntries() > 0:
466 if not testH.GetSumw2N():
468 testH.DrawNormalized(
'ex0 P')
470 print "--> Warning! You tried to normalize a histogram which seems to be already scaled properly. Draw it unscaled."
471 scaleToIntegral =
False
477 if testH.GetEntries() > 0:
478 testH.DrawNormalized(
'same p')
480 testH.Draw(
'same ex0 l')
483 if(options.rebin == -1):
484 refH = refFile.Get(histoPath)
486 refH =
Rebin(refFile,histoPath,options.rebin)
487 if type(refH) != TH1F:
490 refH.SetLineColor(color)
493 if testH.GetEntries() > 0:
494 refH.DrawNormalized(
'same hist')
496 refH.DrawCopy(
'same hist')
498 text = statsBox.AddText(statTemplate % (
'Line',refH.GetMean(), refH.GetRMS()) )
499 text.SetTextColor(color)
503 entries = testH.GetEntries()
505 testH.Scale(1./entries)
506 entries = refH.GetEntries()
509 refH.Scale(1./entries)
510 refH.Draw(
'same hist')
511 divHistos.append(
Divide(testH,refH))
513 if options.maxLogY > 0:
514 maxlY=options.maxLogY
515 if options.maxLogX > 0:
516 maxlX=options.maxLogX
519 tmpHists.extend(testHs)
520 tmpHists.extend(refHs)
521 optimizeRangeMainPad(argv, effPad, tmpHists, maxlX, options.minXaxis, options.maxXaxis, maxlY, options.minYaxis, options.maxYaxis)
525 for histo,color
in zip(divHistos,colors):
527 histo.SetMarkerSize(1)
528 histo.SetMarkerStyle(20)
529 histo.SetMarkerColor(color)
530 histo.GetYaxis().SetLabelSize(0.07)
531 histo.GetYaxis().SetTitleOffset(0.75)
532 histo.GetYaxis().SetTitleSize(0.08)
533 histo.GetXaxis().SetLabelSize(0.08)
534 histo.GetXaxis().SetTitleSize(0.08)
542 histo.Draw(
'same ex0')
545 if options.maxLogX > 0:
546 maxlX=options.maxLogX
547 optimizeRangeSubPad(argv, diffPad, divHistos, maxlX, options.minXaxis, options.maxXaxis, options.minYR, options.maxYR)
555 canvas.Print(options.out)
558 if __name__ ==
'__main__':
def getMaximumIncludingErrors
def LoadCommandlineOptions
def getMinimumIncludingErrors