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 if not config.getContainerMeta ('EventInfo', 'OnnxEnabled'):
81 raise RuntimeError ("You must enable ONNX in order to use HyPER. Please set 'setupONNX: True' in CommonServices.")
82
83 decorator_prefix = _resolve_reco_partons_prefix(self.topology, self.outputName)
84 alg = config.createAlgorithm(
85 "EventReco::RunHyPERAlg", f"RunHyPERAlg_{decorator_prefix}"
86 )
87
88 alg.btagger = self.btagger
89 alg.electrons, alg.electronSelection = config.readNameAndSelection(
90 self.electrons
91 )
92 alg.muons, alg.muonSelection = config.readNameAndSelection(self.muons)
93 alg.jets, alg.jetSelection = config.readNameAndSelection(self.jets)
94 alg.met = config.readName(self.met)
95 alg.eventSelection = self.eventSelection
96 alg.topology = self.topology
97 # Check that config is ok if a particular event was passed for full log
98 if self.fullLogEventNumber > 0:
99 if self.OutputLevel != 3:
100 raise ValueError(
101 "OutputLevel must be 3 (INFO) when tracing only one particular event!"
102 )
103
104 alg.OutputLevel = self.OutputLevel
105 alg.fullLogEventNumber = self.fullLogEventNumber
106
107 def form_even_odd_path(topology, run):
108 base_path = "TopReconstruction/HyPERModels/" + topology
109 even_path = base_path + "_" + run + "_trained_on_even.onnx"
110 odd_path = base_path + "_" + run + "_trained_on_odd.onnx"
111 return even_path, odd_path
112
113 # Confifigure model onnx paths
114 if config.geometry() == LHCPeriod.Run2:
115 if self.topology == "TtbarAllHadronic":
116 even_path, odd_path = form_even_odd_path(
117 "TtbarAllHadronic", "run2"
118 )
119 elif self.topology == "TtbarLJets":
120 even_path, odd_path = form_even_odd_path(
121 "TtbarLJets", "run2"
122 )
123 elif self.topology == "TtbarLJetsNoBTag":
124 even_path, odd_path = form_even_odd_path(
125 "TtbarLJetsNoBTag", "run2"
126 )
127 elif self.topology == "TtbarDiLepton":
128 even_path, odd_path = form_even_odd_path(
129 "TtbarDiLepton",
130 "run3", # For the time being use Run3 models for DiLepton in Run2
131 )
132 else:
133 print("Not being able to set the model paths for the given topology.")
134 raise ValueError("Unknown topology: " + self.topology)
135 elif config.geometry() == LHCPeriod.Run3:
136 if self.topology == "TtbarAllHadronic":
137 even_path, odd_path = form_even_odd_path(
138 "TtbarAllHadronic", "run3"
139 )
140 elif self.topology == "TtbarLJets":
141 even_path, odd_path = form_even_odd_path(
142 "TtbarLJets", "run3"
143 )
144 elif self.topology == "TtbarLJetsNoBTag":
145 even_path, odd_path = form_even_odd_path(
146 "TtbarLJetsNoBTag", "run3"
147 )
148 elif self.topology == "TtbarDiLepton":
149 even_path, odd_path = form_even_odd_path(
150 "TtbarDiLepton", "run3"
151 )
152 else:
153 print("Not being able to set the model paths for the given topology.")
154 raise ValueError("Unknown topology: " + self.topology)
155 else:
156 print("Not being able to set the model paths for the given run period.")
157 raise ValueError(
158 "HyPER models not available for run period: " + config.geometry()
159 )
160
161 # One Athena ONNX inference tool per cross-validation fold. The model
162 # file is a property of each tool's session tool, and is resolved with
163 # the PathResolver by the session tool itself.
164 for handle, model_path in (
165 ("onnxToolTrainedOnEven", even_path),
166 ("onnxToolTrainedOnOdd", odd_path),
167 ):
168 config.addPrivateTool(handle, "AthOnnx::OnnxRuntimeInferenceTool")
169 config.addPrivateTool(
170 handle + ".ORTSessionTool", "AthOnnx::OnnxRuntimeSessionToolCPU"
171 )
172 getattr(alg, handle).ORTSessionTool.ModelFileName = model_path
173
175 if self.topology == "TtbarDiLepton":
176 alg.top_b_p4 = decorator_prefix + "_Top_b_p4_%SYS%"
177 alg.topbar_bbar_p4 = decorator_prefix + "_Topbar_bbar_p4_%SYS%"
178 alg.top_lep_p4 = decorator_prefix + "_Top_lep_p4_%SYS%"
179 alg.topbar_lepbar_p4 = decorator_prefix + "_Topbar_lepbar_p4_%SYS%"
180 if self.topology == "TtbarAllHadronic":
181 alg.top_b_p4 = decorator_prefix + "_Top_b_p4_%SYS%"
182 alg.topbar_bbar_p4 = decorator_prefix + "_Topbar_bbar_p4_%SYS%"
183 alg.top_Wplus_decay0_p4 = (
184 decorator_prefix + "_Top_Wplus_decay0_p4_%SYS%"
185 )
186 alg.top_Wplus_decay1_p4 = (
187 decorator_prefix + "_Top_Wplus_decay1_p4_%SYS%"
188 )
189 alg.topbar_Wminus_decay0_p4 = (
190 decorator_prefix + "_Topbar_Wminus_decay0_p4_%SYS%"
191 )
192 alg.topbar_Wminus_decay1_p4 = (
193 decorator_prefix + "_Topbar_Wminus_decay1_p4_%SYS%"
194 )
195 if self.topology in ["TtbarLJets", "TtbarLJetsNoBTag"]:
196 alg.toplep_b_p4 = decorator_prefix + "_TopLep_b_p4_%SYS%"
197 alg.toplep_lep_p4 = decorator_prefix + "_TopLep_lep_p4_%SYS%"
198 alg.tophad_b_p4 = decorator_prefix + "_TopHad_b_p4_%SYS%"
199 alg.tophad_w_decay0_p4 = decorator_prefix + "_TopHad_W_decay0_p4_%SYS%"
200 alg.tophad_w_decay1_p4 = decorator_prefix + "_TopHad_W_decay1_p4_%SYS%"
201
202 # give appropriate names for the handles to decorate
203 if self.topology == "TtbarAllHadronic":
204 config.addOutputVar(
205 "EventInfo",
206 "TtbarAllHadronic_HyPER_Top1_Indices_%SYS%", # This is the name in the Cpp code.
207 f"{decorator_prefix}_Top1_Indices", # This is the name going to the output tree.
208 auxType="vector_int",
209 )
210 config.addOutputVar(
211 "EventInfo",
212 "TtbarAllHadronic_HyPER_Top1_Score_%SYS%",
213 f"{decorator_prefix}_Top1_Score",
214 auxType="float",
215 )
216 config.addOutputVar(
217 "EventInfo",
218 "TtbarAllHadronic_HyPER_Top2_Indices_%SYS%",
219 f"{decorator_prefix}_Top2_Indices",
220 auxType="vector_int",
221 )
222 config.addOutputVar(
223 "EventInfo",
224 "TtbarAllHadronic_HyPER_Top2_Score_%SYS%",
225 f"{decorator_prefix}_Top2_Score",
226 auxType="float",
227 )
228 config.addOutputVar(
229 "EventInfo",
230 "TtbarAllHadronic_HyPER_W1_Indices_%SYS%",
231 f"{decorator_prefix}_W1_Indices",
232 auxType="vector_int",
233 )
234 config.addOutputVar(
235 "EventInfo",
236 "TtbarAllHadronic_HyPER_W1_Score_%SYS%",
237 f"{decorator_prefix}_W1_Score",
238 auxType="float",
239 )
240 config.addOutputVar(
241 "EventInfo",
242 "TtbarAllHadronic_HyPER_W2_Indices_%SYS%",
243 f"{decorator_prefix}_W2_Indices",
244 auxType="vector_int",
245 )
246 config.addOutputVar(
247 "EventInfo",
248 "TtbarAllHadronic_HyPER_W2_Score_%SYS%",
249 f"{decorator_prefix}_W2_Score",
250 auxType="float",
251 )
253 for output_var in [
254 ("top_b_p4", decorator_prefix + "_Top_b_p4"),
255 ("topbar_bbar_p4", decorator_prefix + "_Topbar_bbar_p4"),
256 (
257 "top_Wplus_decay0_p4",
258 decorator_prefix + "_Top_Wplus_decay0_p4",
259 ),
260 (
261 "top_Wplus_decay1_p4",
262 decorator_prefix + "_Top_Wplus_decay1_p4",
263 ),
264 (
265 "topbar_Wminus_decay0_p4",
266 decorator_prefix + "_Topbar_Wminus_decay0_p4",
267 ),
268 (
269 "topbar_Wminus_decay1_p4",
270 decorator_prefix + "_Topbar_Wminus_decay1_p4",
271 ),
272 ]:
273 config.addOutputVar(
274 "EventInfo",
275 getattr(alg, output_var[0]),
276 output_var[1],
277 auxType="PtEtaPhiMVector",
278 noSys=False,
279 )
280 elif self.topology == "TtbarLJets" or self.topology == "TtbarLJetsNoBTag":
281 config.addOutputVar(
282 "EventInfo",
283 "TtbarLJets_HyPER_Classification_Score_%SYS%",
284 f"{decorator_prefix}_Classification_Score",
285 auxType="float",
286 )
287 config.addOutputVar(
288 "EventInfo",
289 "TtbarLJets_HyPER_TopHad_Indices_%SYS%",
290 f"{decorator_prefix}_TopHad_Indices",
291 auxType="vector_int",
292 )
293 config.addOutputVar(
294 "EventInfo",
295 "TtbarLJets_HyPER_TopHad_Score_%SYS%",
296 f"{decorator_prefix}_TopHad_Score",
297 auxType="float",
298 )
299 config.addOutputVar(
300 "EventInfo",
301 "TtbarLJets_HyPER_TopHad_IDs_%SYS%",
302 f"{decorator_prefix}_TopHad_IDs",
303 auxType="vector_int",
304 )
305 config.addOutputVar(
306 "EventInfo",
307 "TtbarLJets_HyPER_TopLep_Indices_%SYS%",
308 f"{decorator_prefix}_TopLep_Indices",
309 auxType="vector_int",
310 )
311 config.addOutputVar(
312 "EventInfo",
313 "TtbarLJets_HyPER_TopLep_Score_%SYS%",
314 f"{decorator_prefix}_TopLep_Score",
315 auxType="float",
316 )
317 config.addOutputVar(
318 "EventInfo",
319 "TtbarLJets_HyPER_TopLep_IDs_%SYS%",
320 f"{decorator_prefix}_TopLep_IDs",
321 auxType="vector_int",
322 )
323 config.addOutputVar(
324 "EventInfo",
325 "TtbarLJets_HyPER_WHad_Indices_%SYS%",
326 f"{decorator_prefix}_WHad_Indices",
327 auxType="vector_int",
328 )
329 config.addOutputVar(
330 "EventInfo",
331 "TtbarLJets_HyPER_WHad_Score_%SYS%",
332 f"{decorator_prefix}_WHad_Score",
333 auxType="float",
334 )
335 config.addOutputVar(
336 "EventInfo",
337 "TtbarLJets_HyPER_WLep_Indices_%SYS%",
338 f"{decorator_prefix}_WLep_Indices",
339 auxType="vector_int",
340 )
341 config.addOutputVar(
342 "EventInfo",
343 "TtbarLJets_HyPER_WLep_Score_%SYS%",
344 f"{decorator_prefix}_WLep_Score",
345 auxType="float",
346 )
348 for output_var in [
349 ("toplep_b_p4", decorator_prefix + "_TopLep_b_p4"),
350 ("toplep_lep_p4", decorator_prefix + "_TopLep_lep_p4"),
351 ("tophad_b_p4", decorator_prefix + "_TopHad_b_p4"),
352 (
353 "tophad_w_decay0_p4",
354 decorator_prefix + "_TopHad_W_decay0_p4",
355 ),
356 (
357 "tophad_w_decay1_p4",
358 decorator_prefix + "_TopHad_W_decay1_p4",
359 ),
360 ]:
361 config.addOutputVar(
362 "EventInfo",
363 getattr(alg, output_var[0]),
364 output_var[1],
365 auxType="PtEtaPhiMVector",
366 noSys=False,
367 )
368 elif self.topology == "TtbarDiLepton":
369 config.addOutputVar(
370 "EventInfo",
371 "TtbarDiLepton_HyPER_Classification_Score_%SYS%",
372 f"{decorator_prefix}_Classification_Score",
373 auxType="float",
374 )
375 config.addOutputVar(
376 "EventInfo",
377 "TtbarDiLepton_HyPER_Top1_Indices_%SYS%",
378 f"{decorator_prefix}_Top1_Indices",
379 auxType="vector_int",
380 )
381 config.addOutputVar(
382 "EventInfo",
383 "TtbarDiLepton_HyPER_Top1_IDs_%SYS%",
384 f"{decorator_prefix}_Top1_IDs",
385 auxType="vector_int",
386 )
387 config.addOutputVar(
388 "EventInfo",
389 "TtbarDiLepton_HyPER_Top1_Score_%SYS%",
390 f"{decorator_prefix}_Top1_Score",
391 auxType="float",
392 )
393 config.addOutputVar(
394 "EventInfo",
395 "TtbarDiLepton_HyPER_Top2_Indices_%SYS%",
396 f"{decorator_prefix}_Top2_Indices",
397 auxType="vector_int",
398 )
399 config.addOutputVar(
400 "EventInfo",
401 "TtbarDiLepton_HyPER_Top2_Score_%SYS%",
402 f"{decorator_prefix}_Top2_Score",
403 auxType="float",
404 )
405 config.addOutputVar(
406 "EventInfo",
407 "TtbarDiLepton_HyPER_Top2_IDs_%SYS%",
408 f"{decorator_prefix}_Top2_IDs",
409 auxType="vector_int",
410 )
411 config.addOutputVar(
412 "EventInfo",
413 "TtbarDiLepton_HyPER_HE_Score_%SYS%",
414 f"{decorator_prefix}_HE_Score",
415 auxType="float",
416 )
417
419 for output_var in [
420 ("top_b_p4", decorator_prefix + "_Top_b_p4"),
421 ("topbar_bbar_p4", decorator_prefix + "_Topbar_bbar_p4"),
422 (
423 "top_lep_p4",
424 decorator_prefix + "_Top_lep_p4",
425 ),
426 (
427 "topbar_lepbar_p4",
428 decorator_prefix + "_Topbar_lepbar_p4",
429 ),
430 ]:
431 config.addOutputVar(
432 "EventInfo",
433 getattr(alg, output_var[0]),
434 output_var[1],
435 auxType="PtEtaPhiMVector",
436 noSys=False,
437 )
438 else:
439 raise ValueError("Unknown topology: " + self.topology)
void print(char *figname, TCanvas *c1)
makeAlgs(self, config)