ATLAS Offline Software
Loading...
Searching...
No Matches
PlotEFTrk.py
Go to the documentation of this file.
1#!/usr/bin/env python
2# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3# Authors: Calla Hinderks, Federica Piazza
4
5import ROOT
6import math
7
8ROOT.gROOT.SetStyle("ATLAS")
9ROOT.gROOT.SetBatch()
10
11
12
13category_dict = {
14
15 'eff' : 'Efficiencies',
16 'tech_eff' : 'Efficiencies/Technical',
17 'purity' : 'Efficiencies/Purities',
18 'resolution' : 'Resolutions',
19 'parameter' : 'Parameters',
20 'fakerate' : 'FakeRates',
21 'duplrate' : 'Duplicates',
22 'num' : 'Multiplicities',
23 'summary' : 'Multiplicities',
24 'hits' : 'HitsOnTracks',
25 'pixels' : 'PixelClusters',
26 'strips' : 'StripClusters',
27 'tails' : 'Parameters',
28}
29
30resolution_dict = {
31 'resHelp' : 'resHelper',
32 'pullHelp' : 'pullHelper',
33 'pullwidth' : 'pullwidth',
34 'pullmean' : 'pullmean',
35 'res' : 'resolution',
36 'resmean' : 'resmean',
37 'corr' : 'corr'
38}
39
41
42 from argparse import ArgumentParser
43 parser = ArgumentParser( description='Parser for IDTPM plotting' )
44 parser.add_argument( '--test', help="Input test ROOT files", nargs = '+')
45 parser.add_argument( '--ref', help="Input reference ROOT files", nargs = '+')
46 parser.add_argument( '-o', '--output', help="Output directory")
47 parser.add_argument( '--vertex','--pv','--vtx', help="Include this tag if plotting vertex parameters.", action='store_true', default = False)
48 parser.add_argument( '--vertexcategory', help="Type for vertex parameters if plotting vertex. Default is AllPrimary", default = "AllPrimary")
49 parser.add_argument( '--trkAnalysisTest', help='IDTPM TrackAnalysis for test (e.g. TrkAnaEF)', nargs = '+')
50 parser.add_argument( '--trkAnalysisRef', help='IDTPM TrackAnalysis for reference (e.g. TrkAnaEF)', nargs = '+')
51 parser.add_argument( '--chain', help="Trigger chain (or Offline)", default = 'Offline')
52 parser.add_argument( '-t','--type', help="type of plot (eff, tech_eff, purity, resolution, fakerate, duplrate, num, summary)")
53 parser.add_argument( '-p','--param', help="parameter (e.g pt/eta for efficiencies, d0_vs_truth_eta for resolutions, ...)")
54 parser.add_argument( '--resplot', help="which resolution plot ('resHelp','pullHelp','pullwidth','pullmean','res','resmean','corr')", default=None)
55 parser.add_argument( '--log', help="log scale on x axis, y axis or bot (x, y, xy)", default = '')
56 parser.add_argument( '--ymax', help="maximum value for y-axis ", default = 0)
57 parser.add_argument( '--ymin', help="minimum value for y-axis ", default = 0)
58 parser.add_argument( '--ratioyrange', help="range of ratio y-axis", default = None, nargs = '+', type = float)
59 parser.add_argument( '--dim', help="specify 1D or 2D ", default='1D')
60 parser.add_argument( '--pipelineTest', help="Tested pipeline", nargs = '+')
61 parser.add_argument( '--pipelineRef', help="Reference pipeline", nargs = '+')
62 parser.add_argument( '--norm', help="normalize to unit area", action='store_true')
63 parser.add_argument( '--pu-comparison', help="compare different PU samples", action='store_true')
64 parser.add_argument( '--mu', help="<mu> value (will be printed in ATLAS legend)", default = 200)
65 parser.add_argument( '--sample', help="Sample (e.g. 't#bar{t}' / 'single e, p_{T}>10 GeV', ...). Will be printed in ATLAS legend", default = '')
66 parser.add_argument( '--particle', help="Truth particle (e.g. B-hadrons / #tau, p_{T}>15 GeV). Will be printed in ATLAS legend", default = '')
67 parser.add_argument( '--legend-coord', help="xmin, ymin, xmax, ymax TLegend coordinates", default = [0.65,0.65,0.9,0.87], type = float, nargs = '+')
68 parser.add_argument( '--layout', '--l', help="ITk layout of samples (default 03-00-01)", default="03-00-01")
69 parser.add_argument( '--layoutTest', help = "ITk layout of test if different ITk layout", default = None)
70 parser.add_argument( '--layoutRef', help = "ITk layout of ref if different ITk layout", default = None)
71 parser.add_argument( '--tag', help="output file tag", default = '')
72 parser.print_help()
73 return parser.parse_args()
74
76 return obj.InheritsFrom("TEfficiency")
77
78def isTProfile(obj):
79 return obj.InheritsFrom("TProfile")
80
81def getHistoName(category, args):
82
83 par = args.param
84 if args.vertex:
85 match category:
86 case 'Parameters': return f"offl_vtx_{par}" if args.chain == 'Offline' else f"vtx_{par}"
87 case _: return 'None'
88 else:
89 match category:
90 case 'Parameters': return par
91 case 'Resolutions': return f"{resolution_dict[args.resplot]}_{par}"
92 case 'Efficiencies': return f"eff_vs_truth_{par}" if par!="truthMu" else "eff_vs_truthMu"
93 case 'Efficiencies/Technical': return f"eff_vs_truth_{par}" if par!="truthMu" else "eff_vs_truthMu"
94 case 'Efficiencies/Purities': return f"eff_vs_offl_{par}" if par!="truthMu" else "eff_vs_truthMu"
95 case 'FakeRates': return f"fakerate_vs_offl_{par}" if par!="truthMu" else "fakerate_vs_truthMu"
96 case 'Duplicates': return f"duplrate_vs_truth_{par}" if par!="truthMu" else "duplrate_vs_truthMu"
97 case 'Multiplicities': return par
98 case 'HitsOnTracks': return par
99 case 'PixelClusters': return par
100 case 'StripClusters': return par
101 case _: return 'None'
102
103def getHistoPath(cfg, args):
104 if args.vertex:
105 histopath = f"InDetTrackPerfMonPlots/{cfg['trkAnalysis']}/{cfg['chain']}/Vertices/{args.vertexcategory}/{cfg['category']}/{cfg['histo']}"
106 else:
107 histopath = f"InDetTrackPerfMonPlots/{cfg['trkAnalysis']}/{cfg['chain']}/Tracks/{cfg['category']}/{cfg['histo']}" if 'Clusters' not in cfg['category'] else f"InDetTrackPerfMonPlots/{cfg['trkAnalysis']}/Offline/{cfg['category']}/{cfg['histo']}"
108 h = cfg['input'].Get(histopath)
109 if cfg['norm']: h.Scale(1./h.Integral())
110 print(cfg['input'])
111
112 return h
113
114def getConfig (input, chain, pipeline, trkana, args, color, markstyle, linestyle, isRef=False):
115
116 category = category_dict[args.type.split('_vs_')[0]] #Efficiencies, Resolutions, FakeRates, ...
117 histo = getHistoName(category, args)
118
119 config_dict = {
120 'pipeline' : pipeline,
121 'chain' : chain,
122 'isReference' : isRef,
123 'input' : input,
124 'trkAnalysis' : trkana,
125 'category' : category,
126 'histo' : histo,
127 'legend' : pipeline,
128 'linestyle' : linestyle,
129 'linecolor' : color,
130 'markstyle' : markstyle,
131 'markcolor' : color,
132 'log' : args.log,
133 'ymax' : float(args.ymax),
134 'ymin' : float(args.ymin),
135 'ratioyrange' : args.ratioyrange,
136 'dimension' : args.dim,
137 'norm' : args.norm,
138 }
139
140 return config_dict
141
142
143def getLegend(xmin,ymin,xmax,ymax):
144
145 leg = ROOT.TLegend(xmin,ymin,xmax,ymax)
146 leg.SetFillColor(0)
147 leg.SetLineColor(0)
148 leg.SetBorderSize(0)
149 leg.SetTextSize(0.05)
150 leg.SetTextFont(42)
151 leg.SetLineWidth(2)
152
153 return leg
154
156
157 sample = ''
158 if args.sample == '':
159 if 'ttbar' in args.ref[0]: sample = 't#bar{t}'
160 if 'SingleMu' in args.ref[0]: sample = 'single #mu'
161 if 'SinglePi' in args.ref[0]: sample = 'single #pi'
162 if 'SingleEl' in args.ref[0]: sample = 'single e'
163 if 'pT10_' in args.ref[0]: sample += ', p_{T} = 10 GeV'
164 if 'pT100' in args.ref[0]: sample += ', p_{T} = 100 GeV'
165 if 'pT1_' in args.ref[0]: sample += ', p_{T} = 1 GeV'
166 else: sample = args.sample
167 if args.particle != '': sample += f', {args.particle}'
168
169 diffItkLayout = args.layoutTest != args.layoutRef
170 itklayout = f"{args.layoutTest} vs {args.layoutRef}" if diffItkLayout else f"ITk Layout: {args.layout}"
171 subatlas = ROOT.TLatex(.2, .84, "#splitline{#bf{#it{ATLAS}} Simulation Internal}{#splitline{#sqrt{s} = 14 TeV, HL-LHC}{#splitline{%s}{<#mu> = %s, %s}}}" %(itklayout, args.mu, sample))
172 if args.pu_comparison:
173 subatlas = ROOT.TLatex(.2, .84, "#splitline{#bf{#it{ATLAS}} Simulation Internal}{#splitline{#sqrt{s} = 14 TeV, HL-LHC}{#splitline{%s}{%s}}}" %(itklayout,sample))
174
175 subatlas.SetNDC(1)
176 subatlas.SetTextFont(42)
177 subatlas.SetTextSize(0.05)
178
179 return subatlas
180
181def getPadSizes(args, NRef):
182
183 pad_heights = [600*0.65]
184
185 for nref in range(NRef-1): pad_heights.append(600*0.35 * (1-0.05-1/3))
186 pad_heights.append(600*0.35)
187
188 return pad_heights
189
190def getCanvas(args,cfg, NRef):
191
192 pad_heights = getPadSizes(args, NRef)
193 canv_heigh = sum(pad_heights)
194 pad_bottom = [(1-sum([pad_heights[j] for j in range(i+1)])/canv_heigh) for i in range(len(pad_heights))]
195 canv = ROOT.TCanvas("c","c",600,int(canv_heigh))
196
197 canv.cd()
198 pad1 = ROOT.TPad("pad1","pad1",0,pad_bottom[0],1,1)
199 pad1.SetNumber(1)
200 pad1.SetBottomMargin(0.05)
201
202 ratio_pads = []
203
204 for r in range(NRef):
205 ratio_pads.append(ROOT.TPad(f"pad{r+2}",f"pad{r+2}",0,pad_bottom[r+1],1,pad_bottom[r]))
206 ratio_pads[r].SetTopMargin(0.05)
207 ratio_pads[r].SetBottomMargin(0.05 if r!=(NRef-1) else 1./3.)
208 ratio_pads[r].SetNumber(r+2)
209
210 if cfg['log'] == 'x':
211 pad1.SetLogx()
212 for r in range(NRef): ratio_pads[r].SetLogx()
213
214 if cfg['log'] == 'y':
215 pad1.SetLogy()
216
217 if cfg['log'] == 'xy':
218 pad1.SetLogx()
219 pad1.SetLogy()
220 for r in range(NRef): ratio_pads[r].SetLogx()
221
222 pad1.Draw()
223
224 for r in range(NRef): ratio_pads[r].Draw()
225
226 return canv
227
228def getURDRequirementLine(h, type, canv, scale, logx = False):
229
230 scaleshift = canv.GetPad(1).GetHNDC()/canv.GetPad(2).GetHNDC()
231
232 level = 0.01 if 'rate' in type else 2
233 xmin, xmax = h.GetXaxis().GetXmin(), h.GetXaxis().GetXmax()
234 ymax,ymin = h.GetMaximum(), h.GetMinimum()
235
236 requirement_line = (ROOT.TLine(xmin,level,xmax,level))
237 requirement_line.SetLineStyle(2)
238 requirement_line.SetLineColor(ROOT.kRed)
239 requirement_line.SetLineWidth(1)
240
241 shiftup = 0.01*scaleshift if 'rate' not in type else 0.01
242 shiftdn = 0.07*scaleshift if 'rate' not in type else 0.07
243 y = level + shiftup*(ymax-ymin) if level < ymax else ymax - shiftdn *(ymax-ymin)
244 x = (.63*(xmax-xmin)+xmin) if not logx else math.exp( math.log(xmin) + 0.63*(math.log(xmax) - math.log(xmin)) )
245
246 requirement_text = ROOT.TLatex(x,y, f"#uparrow URD requirement = {level}" if level > ymax else f"URD requirement = {level}")
247 requirement_text.SetTextFont(42)
248 requirement_text.SetTextSize(0.04*scale if 'rate' not in type else 0.04)
249 requirement_text.SetTextColor(ROOT.kRed)
250 return requirement_line, requirement_text
251
252def setStyle(h, cfg):
253
254 h.SetLineColor(cfg['linecolor'])
255 h.SetLineStyle(cfg['linestyle'])
256 h.SetMarkerStyle(cfg['markstyle'])
257 h.SetMarkerColor(cfg['markcolor'])
258 h.SetMarkerSize(0.8)
259 h.SetLineWidth(2)
260
261 if isTEfficiency(h):
262
263 ROOT.gPad.Update()
264
265 if 'Efficiencies' in cfg['category']:
266 h.GetPaintedGraph().SetMaximum(1.2 if cfg['ymax']==0 else cfg['ymax'])
267 h.GetPaintedGraph().SetMinimum(0.7 if cfg['ymin']==0 else cfg['ymin'])
268
269 else:
270
271 if 'y' in str(cfg['log']):
272 h.GetPaintedGraph().SetMaximum(10*max(1,abs(math.log10(max(h.GetPaintedGraph().GetY()))))*max(h.GetPaintedGraph().GetY()) if cfg['ymax']==0 else cfg['ymax'])
273 h.GetPaintedGraph().SetMinimum(max(1e-10, min(h.GetPaintedGraph().GetY())*(0.9)) if cfg['ymin']==0 else cfg['ymin'])
274
275 else:
276 h.GetPaintedGraph().SetMaximum(1.5*float(max(h.GetPaintedGraph().GetY())) if cfg['ymax']==0 else cfg['ymax'])
277 h.GetPaintedGraph().SetMinimum(0 if cfg['ymin']==0 else cfg['ymin'])
278
279 h.GetPaintedGraph().GetXaxis().SetTitleSize(0)
280 h.GetPaintedGraph().GetXaxis().SetLabelSize(0)
281 h.GetPaintedGraph().GetYaxis().SetLabelSize(0.05)
282 h.GetPaintedGraph().GetXaxis().SetTitleSize(0.05)
283
284 else:
285
286 if cfg['norm']:
287 h.SetMaximum(1.5 if cfg['ymax']==0 else cfg['ymax'])
288 h.SetMinimum(0 if cfg['ymin']==0 else cfg['ymin'])
289
290 else:
291
292 if 'y' in str(cfg['log']):
293 h.SetMaximum(1.5*max(1,max(1,abs(math.log10(h.GetMaximum()))))*h.GetMaximum() if cfg['ymax']==0 else cfg['ymax'])
294 h.SetMinimum(max(1e-10, h.GetMinimum()*(0.9)) if cfg['ymin']==0 else cfg['ymin'])
295 if 'avgNum' in cfg['histo']: h.SetMinimum(100 if cfg['ymin']==0 else cfg['ymin'])
296
297 else:
298 h.SetMaximum(1.4*h.GetMaximum() if cfg['ymax']==0 else cfg['ymax'])
299 h.SetMinimum(0 if cfg['ymin']==0 else cfg['ymin'])
300
301 h.GetXaxis().SetTitleSize(0)
302 h.GetXaxis().SetLabelSize(0)
303 h.GetYaxis().SetLabelSize(0.05)
304 h.GetYaxis().SetTitleSize(0.05)
305
306def setRatioStyle(ratio, cfg, color, linestyle, markstyle, ref='C000', multigraph=False, labelsizescale = 65./35., lastpad = False, splittitle = False):
307 if 'vs_truthMu' in cfg['histo']: ratio.GetXaxis().SetTitle('Truth <#mu>')
308 ratio.GetXaxis().SetTitleOffset(1.5)
309 ratio.GetYaxis().SetTitle('#splitline{Ratio wrt}{%s}' %ref if splittitle else 'Ratio wrt %s' %ref)
310 ratio.GetYaxis().SetTitleSize(0.05*labelsizescale)
311 ratio.GetYaxis().SetNdivisions(505)
312 ratio.GetYaxis().SetTitleOffset(1.3*1/labelsizescale)
313
314 if cfg['ratioyrange'] is None:
315
316 if not multigraph:
317 ratio.SetMaximum()
318 ratio.SetMinimum()
319 ratio.GetYaxis().SetRangeUser(max(0.,min(ratio.GetMinimum()-0.1,abs(1.9-ratio.GetMaximum()))),max(ratio.GetMaximum()+0.1,abs(2-ratio.GetMinimum())))
320
321 else:
322 ratio.GetYaxis().SetRangeUser(cfg['ratioyrange'][0],cfg['ratioyrange'][1])
323
324 ratio.GetXaxis().SetLabelSize(0.05*labelsizescale if lastpad else 0)
325 ratio.GetXaxis().SetTitleSize(0.05*labelsizescale if lastpad else 0)
326 ratio.GetYaxis().SetLabelSize(0.05*labelsizescale)
327 ratio.GetYaxis().SetTitleSize(0.05*labelsizescale)
328
329 if not multigraph:
330
331 ratio.SetLineColor(color)
332 ratio.SetLineStyle(linestyle)
333 ratio.SetMarkerStyle(markstyle)
334 ratio.SetMarkerColor(color)
335 ratio.SetMarkerSize(0.8)
336
338
339 xmin, xmax = histos[0].GetPaintedGraph().GetXaxis().GetXmin(), histos[0].GetPaintedGraph().GetXaxis().GetXmax()
340 g1 = ROOT.TGraphAsymmErrors(histos[0].GetPaintedGraph())
341 g2 = ROOT.TGraphAsymmErrors(histos[1].GetPaintedGraph())
342 title = g1.GetXaxis().GetTitle()
343 ratio = ROOT.TGraphAsymmErrors()
344 n, n_ref, n_test = max(g1.GetN(),g2.GetN()), g1.GetN(), g2.GetN()
345 x_ref_arr, y_ref_arr = g1.GetX(), g1.GetY()
346 x_test_arr, y_test_arr = g2.GetX(), g2.GetY()
347 i_test, i_ref = 0, 0
348 err_r_low = []
349 err_r_high = []
350
351 for i in range(n):
352
353 if i_test < n_test and i_ref < n_ref:
354
355 x_ref, y_ref = x_ref_arr[i_ref], y_ref_arr[i_ref]
356 x_test, y_test = x_test_arr[i_test], y_test_arr[i_test]
357 err_ref_low, err_ref_high = g1.GetErrorYlow(i_ref), g1.GetErrorYhigh(i_ref)
358 err_test_low, err_test_high = g2.GetErrorYlow(i_test), g2.GetErrorYhigh(i_test)
359
360 # Check points matching between test and reference
361 if x_test==x_ref:
362 y_ref, y_test = y_ref_arr[i_ref], y_test_arr[i_test]
363 i_test += 1
364 i_ref += 1
365
366 if x_ref>x_test:
367 x_ref = x_test
368 y_ref, y_test = 0, y_test_arr[i_test]
369 i_test+= 1
370
371 if x_test>x_ref:
372 x_test = x_ref
373 y_test, y_ref = 0, y_ref_arr[i_ref]
374 i_ref += 1
375
376 r = y_test / y_ref if y_ref != 0 else 1000
377 if y_test == 0 and y_ref == 0: r = 1
378 err_r_low.append(r * math.sqrt((err_ref_low / y_ref)**2 + (err_test_low / y_test)**2) if y_ref > 0 and y_test > 0 else 0)
379 err_r_high.append(r * math.sqrt((err_ref_high / y_ref)**2 + (err_test_high / y_test)**2) if y_ref > 0 and y_test > 0 else 0)
380 ratio.SetPoint(i, x_ref, r)
381 ratio.GetXaxis().SetTitle(title)
382
383 # Set errors and final x axis range
384 for i in range(ratio.GetN()):
385
386 width = ratio.GetPointX(i+1)-ratio.GetPointX(i) if i < ratio.GetN()-1 else ratio.GetPointX(i)-ratio.GetPointX(i-1)
387 ratio.SetPointError(i, width/2.,width/2., err_r_low[i], err_r_high[i])
388
389 ratio.GetXaxis().SetLimits(xmin, xmax)
390
391 return ratio
392
393def drawTEfficiencyOutliers(r, configs, multigraphs, markers, NRef):
394
395 outliers_index = 0
396
397 for j,g in enumerate(multigraphs[r].GetListOfGraphs()):
398 markers.append([])
399 ROOT.gPad.Update()
400 ymin = ROOT.gPad.GetFrame().GetY1()
401 ymax = ROOT.gPad.GetFrame().GetY2()
402
403 for i in range(g.GetN()):
404
405 if g.GetPointY(i) > ymax:
406 markers[r].append(ROOT.TMarker(g.GetPointX(i), ymax-(ymax-ymin)*0.05, 26))
407 markers[r][outliers_index].SetMarkerColor(configs[j+NRef]['linecolor'])
408 markers[r][outliers_index].SetMarkerSize(1.2)
409 markers[r][outliers_index].Draw('same')
410 outliers_index += 1
411
412 if g.GetPointY(i) < ymin and g.GetPointY(i) > 0:
413 markers[r].append(ROOT.TMarker(g.GetPointX(i), ymin+(ymax-ymin)*0.05, 32))
414 markers[r][outliers_index].SetMarkerColor(configs[j+NRef]['linecolor'])
415 markers[r][outliers_index].SetMarkerSize(1.2)
416 markers[r][outliers_index].Draw('same')
417 outliers_index += 1
418
419def drawTHOutliers(r, configs, ratios, markers, NRef):
420
421 outliers_index = 0
422
423 for j,ratio in enumerate(ratios):
424 ROOT.gPad.Update()
425 ymin = ROOT.gPad.GetFrame().GetY1()
426 ymax = ROOT.gPad.GetFrame().GetY2()
427
428 for i in range(ratio.GetNbinsX()):
429
430 if ratio.GetBinContent(i) > ymax:
431 markers[r].append(ROOT.TMarker(ratio.GetXaxis().GetBinCenter(i), ymax-(ymax-ymin)*0.05, 26))
432 markers[r][outliers_index].SetMarkerColor(configs[j+NRef]['linecolor'])
433 markers[r][outliers_index].SetMarkerSize(1.2)
434 markers[r][outliers_index].Draw('same')
435 outliers_index += 1
436
437 if ratio.GetBinContent(i) < ymin and ratio.GetBinContent(i) > 0:
438 markers[r].append(ROOT.TMarker(ratio.GetXaxis().GetBinCenter(i), ymin+(ymax-ymin)*0.05, 32))
439 markers[r][outliers_index].SetMarkerColor(configs[j+NRef]['linecolor'])
440 markers[r][outliers_index].SetMarkerSize(1.2)
441 markers[r][outliers_index].Draw('same')
442 outliers_index += 1
443
444def drawRefLine(r, ratios, reflines):
445
446 reflines.append(ROOT.TLine(ratios[0].GetXaxis().GetXmin(),1,ratios[0].GetXaxis().GetXmax(),1))
447 reflines[r].SetLineStyle(2)
448 reflines[r].SetLineColor(ROOT.kBlack)
449 reflines[r].SetLineWidth(1)
450 reflines[r].Draw('same')
451
452def draw(args, configs, tails=False, pu_comparison=False):
453
454 NRef = len(args.ref) if not pu_comparison else 1
455 canv = getCanvas(args,configs[0], NRef)
456 ATLASLabel = getATLASLabel(args)
457 legend = getLegend(args.legend_coord[0],args.legend_coord[1],args.legend_coord[2],args.legend_coord[3])
458 doComparison = len(configs) > 1
459 isTEfficiencyObj = False
460 histos = []
461 canv.cd(1)
462
463 for i,cfg in enumerate(configs): # loop over the trkAnalysis to be compared (if single plot, there will be only 1 trkAnalysis)
464 h = getHistoPath(cfg,args)
465 isTEfficiencyObj = isTEfficiency(h)
466 histos.append(h)
467
468 if not tails: h.Draw('same' if i!=0 else '')
469
470 else: h.Draw('sameHISTE' if i%2!=0 else 'samePE')
471
472 setStyle(h, cfg)
473
474 if doComparison and cfg['dimension'] == '1D':
475 draw_option = 'lp'
476
477 if tails:
478 draw_option = 'l' if i%2!=0 else 'lp'
479 jet = 'b-Jet' if i%2==0 else 'LF-Jet'
480 legend.AddEntry(h, f"{cfg['legend']} {jet}",draw_option)
481
482 else: legend.AddEntry(h, cfg['legend'],draw_option)
483
484 legend.Draw()
485
486 ATLASLabel.Draw()
487
488 multigraphs = []
489 reflines = []
490 markers = []
491 urd_lines = []
492 urd_text = []
493
494 # Loop over reference histograms to create one ratio per reference
495 for r in range(NRef):
496
497 labelsizescales = [canv.GetPad(1).GetHNDC()/canv.GetPad(i+2).GetHNDC() for i in range(NRef)]
498 canv.cd(r+2)
499 ratios = []
500 multigraphs.append(ROOT.TMultiGraph())
501 markers.append([])
502
503 if not tails and not pu_comparison:
504
505 for i in range(NRef, len(configs)):
506 ratio_histos = [histos[r] if not isTProfile(histos[r]) else histos[r].ProjectionX(), histos[i] if not isTProfile(histos[i]) else histos[i].ProjectionX()]
507
508 if isTEfficiencyObj: ratios.append(getTEfficiencyRatio(ratio_histos))
509
510 else:
511 ratio = ratio_histos[1].Clone()
512 ratio.Divide(ratio_histos[0])
513 ratios.append(ratio)
514
515 for i, ratio in enumerate(ratios):
516 color = configs[i+NRef]['linecolor'] #if len(configs)>2 else ROOT.kBlack
517 linestyle = configs[i+1]['linestyle']# if len(configs)>2 else 1
518 markstyle = configs[i+1]['markstyle']# if len(configs)>2 else 20
519 setRatioStyle(ratio, configs[i], color, linestyle, markstyle, ref=configs[r]['pipeline'], labelsizescale = labelsizescales[r], lastpad = (r==NRef-1), splittitle = (NRef>1))
520
521 if isTEfficiencyObj:
522 multigraphs[r].Add(ratio,'p')
523
524 else:
525 ratio.Draw('same')
526
527 if isTEfficiencyObj:
528 xmin, xmax = ratios[0].GetXaxis().GetXmin(), ratios[0].GetXaxis().GetXmax()
529 setRatioStyle(multigraphs[r], configs[i], color, linestyle, markstyle, ref=configs[r]['pipeline'], multigraph=True, labelsizescale = labelsizescales[r], lastpad = (r==NRef-1), splittitle = (NRef>1))
530 multigraphs[r].Draw('a')
531 drawTEfficiencyOutliers(r, configs, multigraphs, markers, NRef)
532 multigraphs[r].GetXaxis().SetLimits(xmin, xmax)
533
534 else:
535 drawTHOutliers(r, configs, ratios, markers, NRef)
536
537 drawRefLine(r, ratios, reflines)
538
539 if args.type == 'resolution' and not pu_comparison and 'C000' in args.ref[0]:
540 requirement_line, requirement_text = getURDRequirementLine(ratios[0], 'resolution', canv, labelsizescales[r], logx = ('x' in args.log))
541 urd_lines.append(requirement_line)
542 urd_text.append(requirement_text)
543 urd_lines[r].Draw('same')
544 urd_text[r].Draw('same')
545
546 else:
547 for i in [0,2]:
548 ratio_histos = [histos[i],histos[i+1]]
549 ratio = ratio_histos[0].Clone()
550 ratio.Divide(ratio_histos[1])
551 ratios.append(ratio)
552
553 for i, ratio in enumerate(ratios):
554 color = configs[i*2]['linecolor']
555 linestyle = configs[i*2]['linestyle']
556 markstyle = configs[i*2]['markstyle']
557 setRatioStyle(ratio, configs[i], color, linestyle, markstyle, ref=configs[r]['pipeline'],labelsizescale = labelsizescales[r], lastpad = (r==NRef-1))
558 ratio.GetYaxis().SetTitle('b-Jet / LF-Jet' if tails else '<#mu> = 140/<#mu> = 200')
559 ratio.Draw('same')
560
561 drawRefLine(r, ratios, reflines)
562
563 var = cfg['histo'] if not cfg['category'] == 'Efficiencies/Technical' else cfg['histo'].replace('eff','tech_eff')
564 canv.SaveAs(f"{args.output}/{args.tag+'_' if args.tag != '' else ''}{var}.png")
565
566def main():
567
568 args = GetParserArgs()
569 chain = args.chain
570 inputTest = args.test
571 inputRef = args.ref
572 pipelinesRef = args.pipelineRef
573 pipelinesTest = args.pipelineTest
574 trkanalysesRef = args.trkAnalysisRef
575 trkanalysesTest = args.trkAnalysisTest
576 doTails = (args.type == 'tails')
577 doPUComparison = args.pu_comparison
578
579
580 if not doTails and not doPUComparison:
581 colors = [ ROOT.kRed, ROOT.kBlue, ROOT.kGreen+2, ROOT.kOrange+7, ROOT.kMagenta, ROOT.kCyan+1, ROOT.kViolet, ROOT.kTeal+2, ROOT.kPink+6, ROOT.kAzure+1]
582 linestyles = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
583 markstyles = [ 20, 21, 22, 23, 24, 25, 26, 27, 28, 30 ]
584 inputFiles = inputRef+inputTest
585 pipelines = pipelinesRef+pipelinesTest
586 trkanalyses = trkanalysesRef+trkanalysesTest
587 inputFiles = inputRef+inputTest
588
589 print(pipelines)
590 print(trkanalyses)
591 print(inputFiles)
592
593 configs = []
594
595 for i,pipeline in enumerate(pipelines):
596 isReference = (i<len(pipelinesRef))
597 f = ROOT.TFile.Open(inputFiles[i], 'READ')
598 configs.append(getConfig(f, chain, pipeline, trkanalyses[i], args, colors[i], markstyles[i], linestyles[i], isReference))
599
600 draw(args, configs)
601
602 else:
603
604 colors = [ROOT.kRed, ROOT.kRed, ROOT.kBlue, ROOT.kBlue]
605 linestyles = [2,1,2,1]
606 markstyles = [20,0,24,0] if doTails else [20, 24, 20, 24]
607 pipelines = args.pipelineRef+args.pipelineRef+args.pipelineTest+args.pipelineTest if doTails else args.pipelineRef+args.pipelineTest
608 trkanalyses = args.trkAnalysisRef
609 trkanalyses.extend(args.trkAnalysisTest)
610 inputFiles = inputRef+inputRef+inputTest+inputTest if doTails else inputRef+inputTest
611 configs = []
612
613 for i,trkana in enumerate(trkanalyses):
614 f = ROOT.TFile.Open(inputFiles[i], 'READ')
615 configs.append(getConfig(f, chain, pipelines[i], trkanalyses[i], args, colors[i], markstyles[i], linestyles[i]))
616
617 draw(args, configs, tails=doTails,pu_comparison=doPUComparison)
618
619if __name__ == "__main__":
620 main()
void print(char *figname, TCanvas *c1)
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
T * Get(TFile &f, const std::string &n, const std::string &dir="", const chainmap_t *chainmap=0, std::vector< std::string > *saved=0)
get a histogram given a path, and an optional initial directory if histogram is not found,...
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition hcg.cxx:310
getConfig(input, chain, pipeline, trkana, args, color, markstyle, linestyle, isRef=False)
Definition PlotEFTrk.py:114
getURDRequirementLine(h, type, canv, scale, logx=False)
Definition PlotEFTrk.py:228
drawTHOutliers(r, configs, ratios, markers, NRef)
Definition PlotEFTrk.py:419
setRatioStyle(ratio, cfg, color, linestyle, markstyle, ref='C000', multigraph=False, labelsizescale=65./35., lastpad=False, splittitle=False)
Definition PlotEFTrk.py:306
drawRefLine(r, ratios, reflines)
Definition PlotEFTrk.py:444
getATLASLabel(args)
Definition PlotEFTrk.py:155
getLegend(xmin, ymin, xmax, ymax)
Definition PlotEFTrk.py:143
getCanvas(args, cfg, NRef)
Definition PlotEFTrk.py:190
getTEfficiencyRatio(histos)
Definition PlotEFTrk.py:337
getHistoPath(cfg, args)
Definition PlotEFTrk.py:103
isTEfficiency(obj)
Definition PlotEFTrk.py:75
drawTEfficiencyOutliers(r, configs, multigraphs, markers, NRef)
Definition PlotEFTrk.py:393
GetParserArgs()
Definition PlotEFTrk.py:40
getHistoName(category, args)
Definition PlotEFTrk.py:81
setStyle(h, cfg)
Definition PlotEFTrk.py:252
isTProfile(obj)
Definition PlotEFTrk.py:78
draw(args, configs, tails=False, pu_comparison=False)
Definition PlotEFTrk.py:452
getPadSizes(args, NRef)
Definition PlotEFTrk.py:181