ATLAS Offline Software
Loading...
Searching...
No Matches
InferenceConfig.py
Go to the documentation of this file.
1# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
3from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
4from AthenaConfiguration.ComponentFactory import CompFactory
5
6DEFAULT_BUCKET_MODEL_PATH = "dev/MuonRecRTT/edgecnn_mu200.onnx"
7DEFAULT_BUCKET_SCORE_THRESHOLD = 0.160
8DEFAULT_BUCKET_SINGLE_OUTPUT_MODE = "logit"
9
10def MuonLearningOnnxRuntimeSvcCfg(flags, name="OnnxRuntimeSvc", **kwargs):
11 """Configure the shared ONNX Runtime service used by MuonLearning tools."""
12 result = ComponentAccumulator()
13 kwargs.setdefault("LogLevel", 3)
14 svc = CompFactory.AthOnnx.OnnxRuntimeSvc(name, **kwargs)
15 result.addService(svc, primary=False, create=True)
16 return result
17
18def GraphInferenceAlgCfg(flags, name = "GraphInferenceAlg", **kwargs):
19 result = ComponentAccumulator()
20 the_alg = CompFactory.MuonML.InferenceAlg(name, **kwargs)
21 result.addEventAlgo(the_alg, primary = True)
22 return result
23
24def GraphSPFilterToolCfg(flags, name ="GraphSPFilterTool", **kwargs):
25
26 from AthOnnxComps.OnnxRuntimeSessionConfig import OnnxRuntimeSessionToolCfg
27
28 result = ComponentAccumulator()
29 kwargs.setdefault("ModelSession", result.popToolsAndMerge(OnnxRuntimeSessionToolCfg(flags, model_fname="/eos/atlas/atlascerngroupdisk/data-art/grid-input/MuonRecRTT/TestModel.onnx")))
30 kwargs.setdefault("MLFilterCut", -3.6) # Working point cut
31
32 the_tool = CompFactory.MuonML.GraphSPFilterTool(name, **kwargs)
33 result.setPrivateTools(the_tool)
34 return result
35
36def GraphBucketFilterToolCfg(flags, name ="GraphBucketFilterTool", **kwargs):
37
38 from AthOnnxComps.OnnxRuntimeSessionConfig import OnnxRuntimeSessionToolCfg
39
40 result = ComponentAccumulator()
41 model_path = kwargs.pop("ModelPath", DEFAULT_BUCKET_MODEL_PATH)
42 single_output_mode = kwargs.pop("SingleOutputMode", None)
43 if single_output_mode is not None:
44 if "SingleOutputIsLogit" in kwargs:
45 raise ValueError(
46 "Specify either SingleOutputMode or SingleOutputIsLogit, not both."
47 )
48 if single_output_mode not in ("logit", "prob"):
49 raise ValueError(
50 "SingleOutputMode must be 'logit' or 'prob', got "
51 f"{single_output_mode!r}."
52 )
53 kwargs["SingleOutputIsLogit"] = (single_output_mode == "logit")
54
55 result.merge(MuonLearningOnnxRuntimeSvcCfg(flags))
56 kwargs.setdefault("ModelSession", result.popToolsAndMerge(
57 OnnxRuntimeSessionToolCfg(flags, model_fname=model_path,
58 OnnxRuntimeSvc=result.getService("OnnxRuntimeSvc"))))
59 kwargs.setdefault("OutputLevel", 3) # INFO level (1=VERBOSE, 2=DEBUG, 3=INFO, 4=WARNING, 5=ERROR, 6=FATAL)
60 kwargs.setdefault("ScoreThreshold", DEFAULT_BUCKET_SCORE_THRESHOLD)
61 kwargs.setdefault("OutputName", "logits")
62 kwargs.setdefault("SingleOutputIsLogit", DEFAULT_BUCKET_SINGLE_OUTPUT_MODE == "logit")
63
64 the_tool = CompFactory.MuonML.GraphBucketFilterTool(name, **kwargs)
65 result.setPrivateTools(the_tool)
66 return result
67
68
69def SegmentEdgeClassifierToolCfg(flags, name="SegmentEdgeClassifierTool", **kwargs):
70 from AthOnnxComps.OnnxRuntimeSessionConfig import OnnxRuntimeSessionToolCfg
71
72 result = ComponentAccumulator()
73 model_path = kwargs.pop("ModelPath", "MuonInference/models/edge_gnn_refit_top01_from_t0020.onnx")
74 result.merge(MuonLearningOnnxRuntimeSvcCfg(flags))
75 kwargs.setdefault("ModelSession", result.popToolsAndMerge(
76 OnnxRuntimeSessionToolCfg(flags, model_fname=model_path,
77 OnnxRuntimeSvc=result.getService("OnnxRuntimeSvc"))))
78 # Keep the same ONNX/model properties used by GraphBucketFilterToolCfg in this file.
79 kwargs.setdefault("InputNodeName", "x")
80 kwargs.setdefault("InputEdgeIndexName", "edge_index")
81 kwargs.setdefault("InputEdgeAttrName", "edge_attr")
82 kwargs.setdefault("OutputName", "logits")
83 kwargs.setdefault("MaxDeltaThetaDeg", 35.0)
84 kwargs.setdefault("MaxDeltaSector", 1)
85 kwargs.setdefault("SectorModulo", 16)
86 kwargs.setdefault("ReadSpacePoints", "MuonSpacePoints")
87 # Zero leaves pre-inference pruning disabled.
88 kwargs.setdefault("MaxSegmentsPerBucket", 0)
89 kwargs.setdefault("MaxEdgesPerNodeBeforeInference", 0)
90 kwargs.setdefault("MaxEdgesPerTargetChamberBeforeInference", 0)
91 tool = CompFactory.MuonML.SegmentEdgeClassifierTool(name, **kwargs)
92 result.setPrivateTools(tool)
93 return result
94
95
96def SegmentEdgeInferenceAlgCfg(flags, name="SegmentEdgeInferenceAlg", **kwargs):
97 result = ComponentAccumulator()
98 # Accept a model-path shortcut or an EdgeClassifierTool settings
99 edge_tool_kwargs = {}
100 if "EdgeModelPath" in kwargs:
101 edge_tool_kwargs["ModelPath"] = kwargs.pop("EdgeModelPath")
102 # Unwrap a settings mapping supplied for EdgeClassifierTool.
103 if isinstance(kwargs.get("EdgeClassifierTool"), dict):
104 edge_tool_kwargs.update(kwargs.pop("EdgeClassifierTool"))
105
106 if "EdgeClassifierTool" not in kwargs:
107 kwargs["EdgeClassifierTool"] = result.popToolsAndMerge(
108 SegmentEdgeClassifierToolCfg(flags, **edge_tool_kwargs))
109 kwargs.setdefault("SegmentKey", "MuonSegmentsFromR4")
110 kwargs.setdefault("PairGateDecoration", "MuonSegmentsFromR4.mlTrackComponent")
111 # An empty key disables this optional non-owning view. When enabled it
112 # contains only segments incident to a post-classifier selected edge.
113 kwargs.setdefault("FilteredSegmentKey", "")
114 kwargs.setdefault("PairGateThreshold", 0.975)
115 # Build components from mutual top-K edge associations
116 kwargs.setdefault("UseDegreeCappedComponents", False)
117 kwargs.setdefault("RequireMutualTopKEdges", True)
118 kwargs.setdefault("RecoverOrphanNodes", True)
119 kwargs.setdefault("SeedAnchorsPerComponent", 0)
120 kwargs.setdefault("AnchorInnermostLayer", True)
121 kwargs.setdefault("MinSegmentsPerComponent", 2)
122 alg = CompFactory.MuonML.SegmentEdgeInferenceAlg(name=name, **kwargs)
123 result.addEventAlgo(alg, primary=True)
124 return result
125
126
127def DisplacedVertexInferenceToolCfg(flags, name="DisplacedVertexInferenceTool", **kwargs):
128 """Configure the DisplacedVertex graph-level ONNX inference tool.
129 The current DV ONNX export consumes raw graph tensors with the contract
130 x [N,7], edge_index [2,E], edge_attr [E,5], n_muon_nodes [1] -> logits [1]
131 """
132 from AthOnnxComps.OnnxRuntimeSessionConfig import OnnxRuntimeSessionToolCfg
133
134 result = ComponentAccumulator()
135 model_path = kwargs.pop("ModelPath", "MuonInference/models/edge_class_dv_mu200.onnx")
136
137 result.merge(MuonLearningOnnxRuntimeSvcCfg(flags))
138 kwargs.setdefault("ModelSession", result.popToolsAndMerge(
139 OnnxRuntimeSessionToolCfg(flags, model_fname=model_path,
140 OnnxRuntimeSvc=result.getService("OnnxRuntimeSvc"))))
141 kwargs.setdefault("InputNodeName", "x")
142 kwargs.setdefault("InputEdgeIndexName", "edge_index")
143 kwargs.setdefault("InputEdgeAttrName", "edge_attr")
144 kwargs.setdefault("InputNMuonNodesName", "n_muon_nodes")
145 kwargs.setdefault("OutputName", "logits")
146 kwargs.setdefault("SingleOutputMode", "logit")
147 if "SpacePointKeys" not in kwargs:
148 sp_containers = []
149 if flags.Detector.GeometryMDT or flags.Detector.GeometryRPC or flags.Detector.GeometryTGC:
150 sp_containers.append("MuonSpacePoints")
151 elif flags.Detector.GeometryMM or flags.Detector.GeometrysTGC:
152 sp_containers.append("NswSpacePoints")
153 kwargs.setdefault("SpacePointKeys", sp_containers)
154 kwargs.setdefault("UseBucketSegmentSelection", True)
155 kwargs.setdefault("MinTowerEnergyMeV", 1000.0)
156 kwargs.setdefault("MaxTowerSegmentDR", 0.4)
157 kwargs.setdefault("CaloRMaxMm", 4250.0)
158 kwargs.setdefault("CaloZMaxMm", 6500.0)
159 kwargs.setdefault("SectorModulo", 16)
160 kwargs.setdefault("RequireEdges", False)
161 tool = CompFactory.MuonML.DVInferenceToolBase(name, **kwargs)
162 result.setPrivateTools(tool)
163 return result
164
165
167 """Configure the calorimeter reconstruction used by the DV training converter.
168 """
169 result = ComponentAccumulator()
170
171 # Same reconstruction chain used by MuonBucketDumpConfig.CaloCellsDumperCfg.
172 from CaloRec.CaloRecoConfig import CaloRecoCfg
173 result.merge(CaloRecoCfg(flags))
174
175 from CaloRec.CaloTowerMakerConfig import CaloTowerMakerCfg
176 result.getPrimaryAndMerge(CaloTowerMakerCfg(flags))
177
178 return result
179
180
181def DisplacedVertexInferenceAlgCfg(flags, name="DisplacedVertexInferenceAlg", **kwargs):
182 """Configure a runnable event-level DisplacedVertex inference algorithm."""
183 result = ComponentAccumulator()
184 do_calo_tower_build = kwargs.pop("DoCaloTowerBuild", True)
185 do_ml_bucket_filter = kwargs.pop("DoMLBucketFilter", True)
186 bucket_model_path = kwargs.pop("BucketModelPath", None)
187 bucket_threshold = kwargs.pop("BucketThreshold", None)
188 filtered_bucket_key = kwargs.pop("FilteredBucketKey", "FilteredMlBuckets")
189 use_filtered_buckets_for_dv_graph = kwargs.pop("UseFilteredBucketsForDVGraph", False)
190 alg_output_level = kwargs.get("OutputLevel", None)
191 tool_kwargs = {}
192 for key in (
193 "ModelPath",
194 "InputNodeName",
195 "InputEdgeIndexName",
196 "InputEdgeAttrName",
197 "InputNMuonNodesName",
198 "OutputName",
199 "SingleOutputMode",
200 "SegmentKey",
201 "SpacePointKeys",
202 "UseBucketSegmentSelection",
203 "TowerContainerKey",
204 "MinTowerEnergyMeV",
205 "MaxTowerSegmentDR",
206 "CaloRMaxMm",
207 "CaloZMaxMm",
208 "SectorModulo",
209 "RequireEdges",
210 "MaxEdges",
211 "FallbackToAllSegments",
212 "DebugDumpFirstNNodes",
213 "DebugDumpFirstNEdges",
214 "SpacePointKeys",
215 "UseBucketSegmentSelection",
216 "OutputLevel",
217 ):
218 if key in kwargs:
219 tool_kwargs[key] = kwargs.pop(key)
220
221 if isinstance(kwargs.get("InferenceTool"), dict):
222 tool_kwargs.update(kwargs.pop("InferenceTool"))
223
224 tower_key = tool_kwargs.get("TowerContainerKey", "CombinedTower")
225 if do_calo_tower_build and tower_key:
226 result.merge(DisplacedVertexCaloTowerCfg(flags))
227
228 if do_ml_bucket_filter:
229 bucket_filter_kwargs = {
230 "WriteSpacePointKey": filtered_bucket_key,
231 "ReadSpacePoints": "MuonSpacePoints",
232 }
233 if bucket_model_path is not None:
234 bucket_filter_kwargs["ModelPath"] = bucket_model_path
235 if bucket_threshold is not None:
236 bucket_filter_kwargs["ScoreThreshold"] = bucket_threshold
237 bucket_tool = result.popToolsAndMerge(
238 GraphBucketFilterToolCfg(flags, **bucket_filter_kwargs)
239 )
240 result.merge(
242 flags,
243 name="DVBucketPrefilterAlg",
244 InferenceTools=[bucket_tool],
245 )
246 )
247 if use_filtered_buckets_for_dv_graph:
248 tool_kwargs.setdefault("SpacePointKeys", [filtered_bucket_key])
249 tool_kwargs.setdefault("UseBucketSegmentSelection", True)
250
251 if "InferenceTool" not in kwargs:
252 kwargs["InferenceTool"] = result.popToolsAndMerge(
253 DisplacedVertexInferenceToolCfg(flags, **tool_kwargs)
254 )
255
256 if alg_output_level is not None:
257 kwargs["OutputLevel"] = alg_output_level
258
259 kwargs.setdefault("ScoreDecoration", "EventInfo.dv_score")
260 kwargs.setdefault("RawOutputDecoration", "EventInfo.dv_rawOutput")
261 kwargs.setdefault("PassDecoration", "EventInfo.dv_pass")
262 kwargs.setdefault("NNodesDecoration", "EventInfo.dv_nNodes")
263 kwargs.setdefault("NEdgesDecoration", "EventInfo.dv_nEdges")
264 alg = CompFactory.MuonML.DVInferenceAlg(name=name, **kwargs)
265 result.addEventAlgo(alg, primary=True)
266 return result
DisplacedVertexCaloTowerCfg(flags)
SegmentEdgeInferenceAlgCfg(flags, name="SegmentEdgeInferenceAlg", **kwargs)
GraphInferenceAlgCfg(flags, name="GraphInferenceAlg", **kwargs)
GraphSPFilterToolCfg(flags, name="GraphSPFilterTool", **kwargs)
SegmentEdgeClassifierToolCfg(flags, name="SegmentEdgeClassifierTool", **kwargs)
DisplacedVertexInferenceAlgCfg(flags, name="DisplacedVertexInferenceAlg", **kwargs)
MuonLearningOnnxRuntimeSvcCfg(flags, name="OnnxRuntimeSvc", **kwargs)
GraphBucketFilterToolCfg(flags, name="GraphBucketFilterTool", **kwargs)
DisplacedVertexInferenceToolCfg(flags, name="DisplacedVertexInferenceTool", **kwargs)