ATLAS Offline Software
Loading...
Searching...
No Matches
HyPERConfig.py
Go to the documentation of this file.
1# Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
2
3from AnalysisAlgorithmsConfig.ConfigBlock import ConfigBlock
4from AthenaConfiguration.Enums import LHCPeriod
5
6from ReconstructionUtils.ReconstructionAlgorithmsUtils import _resolve_reco_partons_prefix
7
8
9class HyPERBlock(ConfigBlock):
10 """ConfigBlock for HyPER algorithms"""
11
12 def __init__(self):
13 super(HyPERBlock, self).__init__()
14 self.addOption(
15 "btagger",
16 "GN2v01_Continuous",
17 type=str,
18 info="the b-tagging algorithm used to determine the PCBT quantile. Irrelevant for the `TtbarLJetsNoBTag` topology. The available models have been trained using GN2.",
19 )
20 self.addOption(
21 "electrons",
22 "",
23 type=str,
24 info="the input electron container, with a possible selection, in the format `container` or `container.selection`.",
25 )
26 self.addOption(
27 "muons",
28 "",
29 type=str,
30 info="the input muon container, with a possible selection, in the format `container` or `container.selection`.",
31 )
32 self.addOption(
33 "jets",
34 "",
35 type=str,
36 info="the input jet container, with a possible selection, in the format `container` or `container.selection`.",
37 )
38 self.addOption("met", "", type=str, info="the input MET container.")
39 self.addOption(
40 "eventSelection",
41 "",
42 type=str,
43 info="an optional event filter to run on. Make sure your selection makes sense in order to build the HyPER graph. For instance, a pre-selection of events containing three jets will not allow you to reconstruct two tops.",
44 )
45 self.addOption(
46 "topology",
47 "",
48 type=str,
49 info="the HyPER model to run. Currently `TtbarAllHadronic`, `TtbarLJetsNoBTag`, `TtbarLJets` and `TtbarDiLepton` are supported.",
50 )
51 self.addOption(
52 "writeRecoPartonsKinematics",
53 False,
54 type=bool,
55 info="whether to publish partial reconstructed parton four-vectors following the `{topology}_{producer}` naming contract.",
56 )
57 self.addOption(
58 "outputName",
59 "HyPER",
60 type=str,
61 info=(
62 "name of the algorithm instance. This is used as a label for the output branches which allows multiple HyPER instances to be run."
63 "The final prefix is `<topology>_<producer>`, using the configured topology. "
64 "For example if `topology=TtbarDiLepton` and `outputName=HyPER`, the output branches will be named `TtbarDiLepton_HyPER_<branch>`. "
65 ),
66 )
67 self.addOption(
68 "OutputLevel",
69 3,
70 type=int,
71 info="the verbosity of the algorithm. This is for debugging purposes. Options: 3 (INFO), 2 (DEBUG), 1 (VERBOSE).",
72 )
73 self.addOption("fullLogEventNumber", 0, type=int, info="TODO")
74
75 def instanceName(self):
76 """Return the instance name for this block"""
77 return self.outputName
78
79 def makeAlgs(self, config):
80 decorator_prefix = _resolve_reco_partons_prefix(self.topology, self.outputName)
81 alg = config.createAlgorithm(
82 "EventReco::RunHyPERAlg", f"RunHyPERAlg_{decorator_prefix}"
83 )
84
85 alg.btagger = self.btagger
86 alg.electrons, alg.electronSelection = config.readNameAndSelection(
87 self.electrons
88 )
89 alg.muons, alg.muonSelection = config.readNameAndSelection(self.muons)
90 alg.jets, alg.jetSelection = config.readNameAndSelection(self.jets)
91 alg.met = config.readName(self.met)
92 alg.eventSelection = self.eventSelection
93 alg.topology = self.topology
94 # Check that config is ok if a particular event was passed for full log
95 if self.fullLogEventNumber > 0:
96 if self.OutputLevel != 3:
97 raise ValueError(
98 "OutputLevel must be 3 (INFO) when tracing only one particular event!"
99 )
100
101 alg.OutputLevel = self.OutputLevel
102 alg.fullLogEventNumber = self.fullLogEventNumber
103
104 def form_even_odd_path(topology, run):
105 base_path = "TopReconstruction/HyPERModels/" + topology
106 even_path = base_path + "_" + run + "_trained_on_even.onnx"
107 odd_path = base_path + "_" + run + "_trained_on_odd.onnx"
108 return even_path, odd_path
109
110 # Confifigure model onnx paths
111 if config.geometry() == LHCPeriod.Run2:
112 if self.topology == "TtbarAllHadronic":
113 even_path, odd_path = form_even_odd_path(
114 "TtbarAllHadronic", "run2"
115 )
116 elif self.topology == "TtbarLJets":
117 even_path, odd_path = form_even_odd_path(
118 "TtbarLJets", "run2"
119 )
120 elif self.topology == "TtbarLJetsNoBTag":
121 even_path, odd_path = form_even_odd_path(
122 "TtbarLJetsNoBTag", "run2"
123 )
124 elif self.topology == "TtbarDiLepton":
125 even_path, odd_path = form_even_odd_path(
126 "TtbarDiLepton",
127 "run3", # For the time being use Run3 models for DiLepton in Run2
128 )
129 else:
130 print("Not being able to set the model paths for the given topology.")
131 raise ValueError("Unknown topology: " + self.topology)
132 elif config.geometry() == LHCPeriod.Run3:
133 if self.topology == "TtbarAllHadronic":
134 even_path, odd_path = form_even_odd_path(
135 "TtbarAllHadronic", "run3"
136 )
137 elif self.topology == "TtbarLJets":
138 even_path, odd_path = form_even_odd_path(
139 "TtbarLJets", "run3"
140 )
141 elif self.topology == "TtbarLJetsNoBTag":
142 even_path, odd_path = form_even_odd_path(
143 "TtbarLJetsNoBTag", "run3"
144 )
145 elif self.topology == "TtbarDiLepton":
146 even_path, odd_path = form_even_odd_path(
147 "TtbarDiLepton", "run3"
148 )
149 else:
150 print("Not being able to set the model paths for the given topology.")
151 raise ValueError("Unknown topology: " + self.topology)
152 else:
153 print("Not being able to set the model paths for the given run period.")
154 raise ValueError(
155 "HyPER models not available for run period: " + config.geometry()
156 )
157
158 # One Athena ONNX inference tool per cross-validation fold. The model
159 # file is a property of each tool's session tool, and is resolved with
160 # the PathResolver by the session tool itself.
161 for handle, model_path in (
162 ("onnxToolTrainedOnEven", even_path),
163 ("onnxToolTrainedOnOdd", odd_path),
164 ):
165 config.addPrivateTool(handle, "AthOnnx::OnnxRuntimeInferenceTool")
166 config.addPrivateTool(
167 handle + ".ORTSessionTool", "AthOnnx::OnnxRuntimeSessionToolCPU"
168 )
169 getattr(alg, handle).ORTSessionTool.ModelFileName = model_path
170
172 if self.topology == "TtbarDiLepton":
173 alg.top_b_p4 = decorator_prefix + "_Top_b_p4_%SYS%"
174 alg.topbar_bbar_p4 = decorator_prefix + "_Topbar_bbar_p4_%SYS%"
175 alg.top_lep_p4 = decorator_prefix + "_Top_lep_p4_%SYS%"
176 alg.topbar_lepbar_p4 = decorator_prefix + "_Topbar_lepbar_p4_%SYS%"
177 if self.topology == "TtbarAllHadronic":
178 alg.top_b_p4 = decorator_prefix + "_Top_b_p4_%SYS%"
179 alg.topbar_bbar_p4 = decorator_prefix + "_Topbar_bbar_p4_%SYS%"
180 alg.top_Wplus_decay0_p4 = (
181 decorator_prefix + "_Top_Wplus_decay0_p4_%SYS%"
182 )
183 alg.top_Wplus_decay1_p4 = (
184 decorator_prefix + "_Top_Wplus_decay1_p4_%SYS%"
185 )
186 alg.topbar_Wminus_decay0_p4 = (
187 decorator_prefix + "_Topbar_Wminus_decay0_p4_%SYS%"
188 )
189 alg.topbar_Wminus_decay1_p4 = (
190 decorator_prefix + "_Topbar_Wminus_decay1_p4_%SYS%"
191 )
192 if self.topology in ["TtbarLJets", "TtbarLJetsNoBTag"]:
193 alg.toplep_b_p4 = decorator_prefix + "_TopLep_b_p4_%SYS%"
194 alg.toplep_lep_p4 = decorator_prefix + "_TopLep_lep_p4_%SYS%"
195 alg.tophad_b_p4 = decorator_prefix + "_TopHad_b_p4_%SYS%"
196 alg.tophad_w_decay0_p4 = decorator_prefix + "_TopHad_W_decay0_p4_%SYS%"
197 alg.tophad_w_decay1_p4 = decorator_prefix + "_TopHad_W_decay1_p4_%SYS%"
198
199 # give appropriate names for the handles to decorate
200 if self.topology == "TtbarAllHadronic":
201 config.addOutputVar(
202 "EventInfo",
203 "TtbarAllHadronic_HyPER_Top1_Indices_%SYS%", # This is the name in the Cpp code.
204 f"{decorator_prefix}_Top1_Indices", # This is the name going to the output tree.
205 auxType="vector_int",
206 )
207 config.addOutputVar(
208 "EventInfo",
209 "TtbarAllHadronic_HyPER_Top1_Score_%SYS%",
210 f"{decorator_prefix}_Top1_Score",
211 auxType="float",
212 )
213 config.addOutputVar(
214 "EventInfo",
215 "TtbarAllHadronic_HyPER_Top2_Indices_%SYS%",
216 f"{decorator_prefix}_Top2_Indices",
217 auxType="vector_int",
218 )
219 config.addOutputVar(
220 "EventInfo",
221 "TtbarAllHadronic_HyPER_Top2_Score_%SYS%",
222 f"{decorator_prefix}_Top2_Score",
223 auxType="float",
224 )
225 config.addOutputVar(
226 "EventInfo",
227 "TtbarAllHadronic_HyPER_W1_Indices_%SYS%",
228 f"{decorator_prefix}_W1_Indices",
229 auxType="vector_int",
230 )
231 config.addOutputVar(
232 "EventInfo",
233 "TtbarAllHadronic_HyPER_W1_Score_%SYS%",
234 f"{decorator_prefix}_W1_Score",
235 auxType="float",
236 )
237 config.addOutputVar(
238 "EventInfo",
239 "TtbarAllHadronic_HyPER_W2_Indices_%SYS%",
240 f"{decorator_prefix}_W2_Indices",
241 auxType="vector_int",
242 )
243 config.addOutputVar(
244 "EventInfo",
245 "TtbarAllHadronic_HyPER_W2_Score_%SYS%",
246 f"{decorator_prefix}_W2_Score",
247 auxType="float",
248 )
250 for output_var in [
251 ("top_b_p4", decorator_prefix + "_Top_b_p4"),
252 ("topbar_bbar_p4", decorator_prefix + "_Topbar_bbar_p4"),
253 (
254 "top_Wplus_decay0_p4",
255 decorator_prefix + "_Top_Wplus_decay0_p4",
256 ),
257 (
258 "top_Wplus_decay1_p4",
259 decorator_prefix + "_Top_Wplus_decay1_p4",
260 ),
261 (
262 "topbar_Wminus_decay0_p4",
263 decorator_prefix + "_Topbar_Wminus_decay0_p4",
264 ),
265 (
266 "topbar_Wminus_decay1_p4",
267 decorator_prefix + "_Topbar_Wminus_decay1_p4",
268 ),
269 ]:
270 config.addOutputVar(
271 "EventInfo",
272 getattr(alg, output_var[0]),
273 output_var[1],
274 auxType="PtEtaPhiMVector",
275 noSys=False,
276 )
277 elif self.topology == "TtbarLJets" or self.topology == "TtbarLJetsNoBTag":
278 config.addOutputVar(
279 "EventInfo",
280 "TtbarLJets_HyPER_Classification_Score_%SYS%",
281 f"{decorator_prefix}_Classification_Score",
282 auxType="float",
283 )
284 config.addOutputVar(
285 "EventInfo",
286 "TtbarLJets_HyPER_TopHad_Indices_%SYS%",
287 f"{decorator_prefix}_TopHad_Indices",
288 auxType="vector_int",
289 )
290 config.addOutputVar(
291 "EventInfo",
292 "TtbarLJets_HyPER_TopHad_Score_%SYS%",
293 f"{decorator_prefix}_TopHad_Score",
294 auxType="float",
295 )
296 config.addOutputVar(
297 "EventInfo",
298 "TtbarLJets_HyPER_TopHad_IDs_%SYS%",
299 f"{decorator_prefix}_TopHad_IDs",
300 auxType="vector_int",
301 )
302 config.addOutputVar(
303 "EventInfo",
304 "TtbarLJets_HyPER_TopLep_Indices_%SYS%",
305 f"{decorator_prefix}_TopLep_Indices",
306 auxType="vector_int",
307 )
308 config.addOutputVar(
309 "EventInfo",
310 "TtbarLJets_HyPER_TopLep_Score_%SYS%",
311 f"{decorator_prefix}_TopLep_Score",
312 auxType="float",
313 )
314 config.addOutputVar(
315 "EventInfo",
316 "TtbarLJets_HyPER_TopLep_IDs_%SYS%",
317 f"{decorator_prefix}_TopLep_IDs",
318 auxType="vector_int",
319 )
320 config.addOutputVar(
321 "EventInfo",
322 "TtbarLJets_HyPER_WHad_Indices_%SYS%",
323 f"{decorator_prefix}_WHad_Indices",
324 auxType="vector_int",
325 )
326 config.addOutputVar(
327 "EventInfo",
328 "TtbarLJets_HyPER_WHad_Score_%SYS%",
329 f"{decorator_prefix}_WHad_Score",
330 auxType="float",
331 )
332 config.addOutputVar(
333 "EventInfo",
334 "TtbarLJets_HyPER_WLep_Indices_%SYS%",
335 f"{decorator_prefix}_WLep_Indices",
336 auxType="vector_int",
337 )
338 config.addOutputVar(
339 "EventInfo",
340 "TtbarLJets_HyPER_WLep_Score_%SYS%",
341 f"{decorator_prefix}_WLep_Score",
342 auxType="float",
343 )
345 for output_var in [
346 ("toplep_b_p4", decorator_prefix + "_TopLep_b_p4"),
347 ("toplep_lep_p4", decorator_prefix + "_TopLep_lep_p4"),
348 ("tophad_b_p4", decorator_prefix + "_TopHad_b_p4"),
349 (
350 "tophad_w_decay0_p4",
351 decorator_prefix + "_TopHad_W_decay0_p4",
352 ),
353 (
354 "tophad_w_decay1_p4",
355 decorator_prefix + "_TopHad_W_decay1_p4",
356 ),
357 ]:
358 config.addOutputVar(
359 "EventInfo",
360 getattr(alg, output_var[0]),
361 output_var[1],
362 auxType="PtEtaPhiMVector",
363 noSys=False,
364 )
365 elif self.topology == "TtbarDiLepton":
366 config.addOutputVar(
367 "EventInfo",
368 "TtbarDiLepton_HyPER_Classification_Score_%SYS%",
369 f"{decorator_prefix}_Classification_Score",
370 auxType="float",
371 )
372 config.addOutputVar(
373 "EventInfo",
374 "TtbarDiLepton_HyPER_Top1_Indices_%SYS%",
375 f"{decorator_prefix}_Top1_Indices",
376 auxType="vector_int",
377 )
378 config.addOutputVar(
379 "EventInfo",
380 "TtbarDiLepton_HyPER_Top1_IDs_%SYS%",
381 f"{decorator_prefix}_Top1_IDs",
382 auxType="vector_int",
383 )
384 config.addOutputVar(
385 "EventInfo",
386 "TtbarDiLepton_HyPER_Top1_Score_%SYS%",
387 f"{decorator_prefix}_Top1_Score",
388 auxType="float",
389 )
390 config.addOutputVar(
391 "EventInfo",
392 "TtbarDiLepton_HyPER_Top2_Indices_%SYS%",
393 f"{decorator_prefix}_Top2_Indices",
394 auxType="vector_int",
395 )
396 config.addOutputVar(
397 "EventInfo",
398 "TtbarDiLepton_HyPER_Top2_Score_%SYS%",
399 f"{decorator_prefix}_Top2_Score",
400 auxType="float",
401 )
402 config.addOutputVar(
403 "EventInfo",
404 "TtbarDiLepton_HyPER_Top2_IDs_%SYS%",
405 f"{decorator_prefix}_Top2_IDs",
406 auxType="vector_int",
407 )
408 config.addOutputVar(
409 "EventInfo",
410 "TtbarDiLepton_HyPER_HE_Score_%SYS%",
411 f"{decorator_prefix}_HE_Score",
412 auxType="float",
413 )
414
416 for output_var in [
417 ("top_b_p4", decorator_prefix + "_Top_b_p4"),
418 ("topbar_bbar_p4", decorator_prefix + "_Topbar_bbar_p4"),
419 (
420 "top_lep_p4",
421 decorator_prefix + "_Top_lep_p4",
422 ),
423 (
424 "topbar_lepbar_p4",
425 decorator_prefix + "_Topbar_lepbar_p4",
426 ),
427 ]:
428 config.addOutputVar(
429 "EventInfo",
430 getattr(alg, output_var[0]),
431 output_var[1],
432 auxType="PtEtaPhiMVector",
433 noSys=False,
434 )
435 else:
436 raise ValueError("Unknown topology: " + self.topology)
void print(char *figname, TCanvas *c1)
makeAlgs(self, config)