ATLAS Offline Software
Loading...
Searching...
No Matches
CheckAppliedSFs.py
Go to the documentation of this file.
1# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
2
3#!/usr/bin/env python
4from array import array
5import ROOT, argparse, sys, gc, os, math
6from PlotUtils import PlotUtils, DiagnosticHisto
7
8
9
11 def __init__(self,
12 var_name = "", axis_title ="",
13 bins = -1, bmin = 0., bmax = 0., bin_width = -1,
14 bdir = None,
15
16 name_old_rel ="", name_new_rel ="",
17
18 test_tree = None,
19 branch_old = "", branch_new = "",
20 weight_old = None, weight_new = None,
21 log_binning = False
22 ):
23
24 self.__old_branch = test_tree.GetLeaf(branch_old)
25 self.__new_branch = test_tree.GetLeaf(branch_new)
26 if not self.__old_branch:
27 raise NameError("Could not find "+branch_old+" in the Tree")
28
29 if not self.__new_branch:
30 raise NameError("Could not find "+branch_new+" in the Tree")
31
32 self.__old_weight = 1. if not weight_old else test_tree.GetLeaf(weight_old)
33 self.__new_weight = 1. if not weight_new else test_tree.GetLeaf(weight_new)
34 if weight_old and not self.__old_weight:
35 raise NameError("Could not find "+weight_old+" in the Tree")
36 if weight_new and not self.__new_weight:
37 raise NameError("Could not find "+weight_new+" in the Tree")
38
39 self.__quality_branch = test_tree.GetLeaf("Muon_quality")
40 if branch_old.find("HighPt") != -1 : self.__quality_branch = test_tree.GetLeaf("Muon_isHighPt")
41 if branch_old.find("LowPt") != -1 : self.__quality_branch = test_tree.GetLeaf("Muon_isLowPt")
42
43 self.__min_quality = 0 if branch_old.find("HighPt") != -1 and branch_old.find("LowPt") != -1 else 1
44 self.__max_quality = 2
45 if branch_old.find("Medium") != -1: self.__max_quality = 1
46 if branch_old.find("Tight") != -1: self.__max_quality = 0
47
48
49 self.__var_name = var_name
51 name = "%s_%s"%(name_old_rel, var_name),
52 axis_title = axis_title,
53 bins = bins, bmin = bmin, bmax = bmax,
54 bin_width = bin_width, bdir = bdir, log_binning = log_binning)
56 name = "%s_%s"%(name_new_rel, var_name),
57 axis_title = axis_title,
58 bins = bins, bmin = bmin, bmax = bmax,
59 bin_width = bin_width, bdir = bdir, log_binning = log_binning)
60
61 def pass_cut(self):
62 return self.__min_quality >= self.__quality_branch .GetValue() and self.__quality_branch.GetValue() <= self.__max_quality
63 def fill(self):
64 if not self.pass_cut(): return
65 self.__old_histo.fill(value = self.__old_branch.GetValue(), weight= self.get_old_weight())
66 self.__new_histo.fill(value = self.__new_branch.GetValue(), weight= self.get_new_weight())
67 def get_old_histo(self):
68 return self.__old_histo
69 def get_new_histo(self):
70 return self.__new_histo
71 def get_old_var(self):
72 return self.__old_branch
73 def get_new_var(self):
74 return self.__new_branch
75 def get_old_weight(self):
76 if isinstance(self.__old_weight, float): return self.__old_weight
77 return self.__old_weight.GetValue()
78 def get_new_weight(self):
79 if isinstance(self.__new_weight, float): return self.__new_weight
80 return self.__new_weight.GetValue()
81 def finalize(self):
82 minimum = min(self.get_old_histo().min(), self.get_new_histo().min()) - 0.01
83 maximum = max(self.get_old_histo().max(), self.get_new_histo().max()) + 0.01
84 for H in [ self.get_old_histo(), self.get_new_histo()]:
85 H.setMinimum(minimum)
86 H.setMaximum(maximum)
87 H.write()
88
89 def name(self):
90 return self.__var_name
92 def __init__(self,
93 var_name = "",
94 axis_title ="",
95 bins = -1,
96
97 name_old_rel ="",
98 name_new_rel ="",
99
100 test_tree = None,
101 branch_old = "",
102 branch_new = "",
103 weight_old = None,
104 weight_new = None,
105
106 branch_sys_old = "",
107 branch_sys_new = "",
108 ):
109 ReleaseComparer.__init__(self,
110 var_name = var_name,
111 axis_title = axis_title,
112 bins = bins, bmin = 5.e-4, bmax = 4.,
113 name_old_rel =name_old_rel,
114 name_new_rel =name_new_rel,
115 test_tree = test_tree,
116 branch_old = branch_old,
117 branch_new = branch_new,
118 weight_old = weight_old,
119 weight_new = weight_new,
120 log_binning = True)
121 self.__sys_old = test_tree.GetLeaf(branch_sys_old)
122 self.__sys_new = test_tree.GetLeaf(branch_sys_new)
123 if not self.__sys_old:
124 raise NameError("Failed to retrieve "+branch_sys_old)
125 if not self.__sys_new:
126 raise NameError("Failed to retrieve "+branch_sys_new)
127
128
129 def fill(self):
130 self.get_old_histo().fill(value = math.fabs(self.get_old_var().GetValue() - self.__sys_old.GetValue()) / (self.get_old_var().GetValue() if self.get_old_var().GetValue() != 0. else 1.) ,
131 weight= self.get_old_weight())
132 self.get_new_histo().fill(value = math.fabs(self.get_new_var().GetValue() - self.__sys_new.GetValue()) / (self.get_new_var().GetValue() if self.get_new_var().GetValue() != 0. else 1.),
133 weight= self.get_new_weight())
134
135
136
137KnownWPs = {
138 "Loose" : "RECO",
139 "Medium" : "RECO",
140 "Tight" : "RECO",
141 "HightPt3Layers":"RECO",
142 "HighPt" : "RECO",
143 "LowPt" : "RECO",
144 "LowPtMVA" : "RECO",
145
146 "TTVA" : "TTVA",
147 "FCLooseIso": "ISO",
148 "FCTight_FixedRadIso": "ISO",
149 "FCLoose_FixedRadIso": "ISO",
150 "FixedCutHighPtTrackOnlyIso": "ISO",
151 "FCTightIso": "ISO",
152 "FixedCutPflowLooseIso": "ISO",
153 "FCTightTrackOnlyIso": "ISO",
154 "FixedCutPflowTightIso": "ISO",
155 "FCTightTrackOnly_FixedRadIso": "ISO",
156 "BadMuonVeto_HighPt" : "BADMUON",
157 }
158
160 parser = argparse.ArgumentParser(description='This script checks applied scale factors written to a file by MuonEfficiencyCorrections/MuonEfficiencyCorrectionsSFFilesTest. For more help type \"python CheckAppliedSFs.py -h\"', prog='CheckAppliedSFs', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
161 parser.add_argument('-i', '--InputFile', help='Specify an input root file', default="SFTest.root")
162 parser.add_argument('-o', '--outDir', help='Specify a destination directory', default="Plots")
163 parser.add_argument('-l', '--label', help='Specify the dataset you used with MuonEfficiencyCorrectionsSFFilesTest', default="Internal")
164 parser.add_argument('-w', '--WP', help='Specify a WP to plot', nargs='+', default=[])
165 parser.add_argument('-c', '--SFConstituent', help='Specify if you want to plot nominal value, sys or stat error', nargs='+', default=["SF","DataEff","MCEff"])
166 parser.add_argument('--bonusname', help='Specify a bonus name for the filename', default="")
167 parser.add_argument('--bonuslabel', help='Specify a bonus label printed in the histogram', default="")
168 parser.add_argument('--noComparison', help='do not plot comparison to old release', action='store_true', default=False)
169 parser.add_argument('-n', '--nBins', help='specify number of bins for histograms', type=int, default=50)
170 return parser
171
173 branchesInFile = [key.GetName() for key in tree.GetListOfBranches()]
174 calibReleases = []
175 allWPs = set([wp for wp in KnownWPs.iterkeys() ])
176 WPs = []
177 for i in branchesInFile:
178 print i
179 if not i.endswith("SF"): continue
180 if not i.startswith("c"): continue
181 calibCand = i[1:-3]
182
183 wp_str = i[ : i.rfind("_")]
184 beststr = wp_str[wp_str.rfind("_")+1 : ]
185 if beststr in allWPs:
186 if not beststr in WPs: WPs.append(beststr)
187 if not calibCand[ : calibCand.find(beststr)-1] in calibReleases: calibReleases.append(calibCand[ : calibCand.find(beststr)-1])
188 print "INFO: Found the following working points: %s"%(", ".join(WPs))
189 return calibReleases, WPs
190
191def getSystematics(tree, wp, calib_release):
192 search_str = "c%s_%s_SF"%(calib_release, wp)
193 syst_names = [key.GetName()[len(search_str) + 2:] for key in tree.GetListOfBranches() if key.GetName().startswith(search_str) and key.GetName() != search_str]
194 print syst_names
195 return syst_names
196
197if __name__ == "__main__":
198 Options = getArgParser().parse_args()
199
200 if not os.path.exists(Options.InputFile):
201 print 'ERROR: File %s does not exist!'%Options.InputFile
202 sys.exit(1)
203 infile = ROOT.TFile(Options.InputFile)
204
205 tree = infile.Get("MuonEfficiencyTest")
206 calibReleases, WPs = getCalibReleasesAndWP(tree)
207
208 if len(calibReleases)==2: print "INFO: Found the following calibration releases to compare: %s"%(",".join(calibReleases))
209
210 if len(Options.WP)>0:
211 userWPs = []
212 for wp in Options.WP:
213 if wp in WPs: userWPs.append(wp)
214 WPs = userWPs
215 print 'INFO: WPs given by user, only plot: %s'%(",".join(WPs))
216
217
218 ROOT.gROOT.Macro("rootlogon.C")
219 ROOT.gROOT.SetStyle("ATLAS")
220 ROOT.gROOT.SetBatch(1)
221 gc.disable()
222
223 if os.path.isdir(Options.outDir) == False:
224 os.system("mkdir -p %s"%(Options.outDir))
225
226 bonusname=Options.bonusname
227
228 Histos = []
229
230 for wp in WPs:
231 systematics = getSystematics(tree,wp, calibReleases[0])+[""]
232 for t in Options.SFConstituent:
233 corrType = "Scale Factor"
234 if t == "DataEff": corrType = "Data efficiency"
235 elif t == "MCEff": corrType = "MC efficiency"
236
237 for var in systematics:
238 if len(var) == 0:
239 Histos += [
241 var_name = "%s_%s"%(wp,t), axis_title = " %s %s"%(corrType,wp),
242 bmin = 1., bin_width = 0.0001,
243 name_old_rel =calibReleases[0], name_new_rel = calibReleases[1],
244 test_tree = tree,
245 branch_old = "c%s_%s_%s"%(calibReleases[0],wp,t), branch_new = "c%s_%s_%s"%(calibReleases[1],wp,t),
246 )]
247 else:
248 Histos +=[
250 var_name = "%s_%s_%s"%(wp,t,var.replace("RECO",KnownWPs[wp])),
251 axis_title = "%s %s (%s)"%(var.replace("RECO",KnownWPs[wp]), corrType,wp),
252 bins = Options.nBins,
253 name_old_rel =calibReleases[0], name_new_rel = calibReleases[1],
254 test_tree = tree,
255 branch_old = "c%s_%s_%s"%(calibReleases[0],wp,t), branch_new = "c%s_%s_%s"%(calibReleases[1],wp,t),
256
257 branch_sys_old = "c%s_%s_%s__%s"%(calibReleases[0],wp,t,var),
258 branch_sys_new = "c%s_%s_%s__%s"%(calibReleases[1],wp,t,var),
259 )]
260
261 continue
262 Histos +=[
263 ReleaseComparer(var_name = "pt_%s"%(wp), axis_title ="p_{T} #mu(%s) [MeV]"%(wp),
264 bins = 15, bmin = 15.e3, bmax = 200.e3,
265 name_old_rel =calibReleases[0], name_new_rel = calibReleases[1],
266 test_tree = tree,
267 branch_old = "Muon_pt", branch_new = "Muon_pt",
268 weight_old = "c%s_%s_SF"%(calibReleases[0],wp),
269 weight_new = "c%s_%s_SF"%(calibReleases[1],wp)),
270
271 ReleaseComparer(var_name = "eta_%s"%(wp), axis_title ="#eta #mu(%s) [MeV]"%(wp),
272 bins = 54, bmin = -2.7, bmax = 2.7,
273 name_old_rel =calibReleases[0], name_new_rel = calibReleases[1],
274 test_tree = tree,
275 branch_old = "Muon_eta", branch_new = "Muon_eta",
276 weight_old = "c%s_%s_SF"%(calibReleases[0],wp),
277 weight_new = "c%s_%s_SF"%(calibReleases[1],wp)),
278 ReleaseComparer(var_name = "phi_%s"%(wp), axis_title ="#phi #mu(%s) [MeV]"%(wp),
279 bins = 16, bmin = -3.15, bmax = 3.15,
280 name_old_rel =calibReleases[0], name_new_rel = calibReleases[1],
281 test_tree = tree,
282 branch_old = "Muon_phi", branch_new = "Muon_phi",
283 weight_old = "c%s_%s_SF"%(calibReleases[0],wp),
284 weight_new = "c%s_%s_SF"%(calibReleases[1],wp)),
285
286 ]
287
288 for i in range(tree.GetEntries()):
289 tree.GetEntry(i)
290 if i > 0 and i % 2500 == 0:
291 print "INFO: %d/%d events processed"%(i, tree.GetEntries())
292
293 if math.fabs(tree.Muon_eta) > 2.5 or math.fabs(tree.Muon_eta) < 0.1 or math.fabs(tree.Muon_pt) > 15.e3: continue
294 for H in Histos:
295 H.fill()
296
297 print "INFO: Histograms filled"
298
299
300
301 if len(calibReleases)==2:
302
303 dummy = ROOT.TCanvas("dummy", "dummy", 800, 600)
304 dummy.SaveAs("%s/AllAppliedSFCheckPlots%s.pdf[" % (Options.outDir, bonusname))
305
306 for comp in Histos:
307 comp.finalize()
308 histoCR1 = comp.get_old_histo().TH1()
309 histoCR2 = comp.get_new_histo().TH1()
310
311 pu = PlotUtils(status = Options.label)
312 pu.Prepare1PadCanvas(comp.name())
313 pu.GetCanvas().SetLogy()
314 if comp.get_old_histo().has_log_binnnig(): pu.GetCanvas().SetLogx()
315
316 histoCR1.GetYaxis().SetTitle("Fraction of muons")
317
318 pu.drawStyling(histoCR1, 1, max([histoCR1.GetMaximum(),histoCR2.GetMaximum()]) *1.e3, TopPad = False)
319 histoCR1.SetTitle("%s, Mean: %.8f"%(calibReleases[0],histoCR1.GetMean()))
320 histoCR2.SetTitle("%s, Mean: %.8f"%(calibReleases[1],histoCR2.GetMean()))
321
322 histoCR1.Draw("sameHIST")
323 histoCR2.SetLineColor(ROOT.kRed)
324 histoCR2.SetMarkerColor(ROOT.kRed)
325 histoCR2.SetLineStyle(9)
326 histoCR2.Draw("sameHIST")
327 pu.CreateLegend(0.2, 0.7, 0.6, 0.8,18)
328
329 pu.AddToLegend([histoCR1, histoCR2])
330
331 variationDrawn = "Nominal"
332 if "STAT" in comp.name(): variationDrawn = "|Stat-Nominal|/Nominal"
333 elif "SYS" in comp.name(): variationDrawn = "|Sys-Nominal|/Nominal"
334 type_drawn = "Scale factor"
335 if comp.name().split("_")[1] == "DataEff": type_drawn = "data efficiency"
336 elif comp.name().split("_")[1] == "MCEff": type_drawn = "MC efficiency"
337 pu.DrawTLatex(0.55, 0.5, Options.bonuslabel)
338 pu.DrawTLatex(0.55, 0.85, "WP: %s, %s"%(comp.name().split("_")[0],variationDrawn))
339 pu.DrawTLatex(0.55, 0.9, type_drawn)
340
341 pu.DrawAtlas(0.2, 0.9)
342 pu.DrawSqrtS(0.2, 0.85)
343
344 pu.DrawLegend()
345 pu.saveHisto("%s/AppliedSFCheck_%s%s"%(Options.outDir, comp.name(),bonusname), ["pdf"])
346 pu.saveHisto("%s/AllAppliedSFCheckPlots%s" % (Options.outDir, bonusname), ["pdf"])
347
348 dummy.SaveAs("%s/AllAppliedSFCheckPlots%s.pdf]" % (Options.outDir, bonusname))
349
350 else:
351 print "INFO: Currently, only release comaparisons are implemented"
352
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
__old_branch
Direct access to the branch which are going to be compared.
__init__(self, var_name="", axis_title="", bins=-1, bmin=0., bmax=0., bin_width=-1, bdir=None, name_old_rel="", name_new_rel="", test_tree=None, branch_old="", branch_new="", weight_old=None, weight_new=None, log_binning=False)
int __old_weight
Weights as a function of the muon kinematics.
__init__(self, var_name="", axis_title="", bins=-1, name_old_rel="", name_new_rel="", test_tree=None, branch_old="", branch_new="", weight_old=None, weight_new=None, branch_sys_old="", branch_sys_new="")
STL class.
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
getSystematics(tree, wp, calib_release)