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