ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
MuonSpectrometer
MuonPhaseII
MuonLearning
MuonInference
python
InferenceConfig.py
Go to the documentation of this file.
1
# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
3
from
AthenaConfiguration.ComponentAccumulator
import
ComponentAccumulator
4
from
AthenaConfiguration.ComponentFactory
import
CompFactory
5
6
DEFAULT_BUCKET_MODEL_PATH =
"dev/MuonRecRTT/edgecnn_mu200.onnx"
7
DEFAULT_BUCKET_SCORE_THRESHOLD = 0.160
8
DEFAULT_BUCKET_SINGLE_OUTPUT_MODE =
"logit"
9
10
def
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
18
def
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
24
def
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
36
def
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
69
def
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
tool = CompFactory.MuonML.SegmentEdgeClassifierTool(name, **kwargs)
88
result.setPrivateTools(tool)
89
return
result
90
91
92
def
SegmentTrackCandidateBuilderToolCfg
(flags, name="SegmentTrackCandidateBuilderTool", **kwargs):
93
result = ComponentAccumulator()
94
# High-purity candidate cores are built with OverlapThreshold.
95
# A second low-threshold recovery pass is added with EdgeThreshold.
96
# This strongly reduces candidate loss from borderline true edges.
97
kwargs.setdefault(
"EdgeThreshold"
, 0.25)
98
kwargs.setdefault(
"OverlapThreshold"
, 0.8)
99
kwargs.setdefault(
"UseRecoveryComponents"
,
True
)
100
kwargs.setdefault(
"SymmetrizeDirectedEdges"
,
True
)
101
kwargs.setdefault(
"AddAllSegmentsRecoveryCandidate"
,
False
)
102
kwargs.setdefault(
"KeepIsolatedSegments"
,
False
)
103
kwargs.setdefault(
"MinCandidateSize"
, 2)
104
tool = CompFactory.MuonML.SegmentTrackCandidateBuilderTool(name, **kwargs)
105
result.setPrivateTools(tool)
106
return
result
107
108
109
def
SegmentEdgeInferenceAlgCfg
(flags, name="SegmentEdgeInferenceAlg", **kwargs):
110
result = ComponentAccumulator()
111
# Accept EdgeModelPath as a convenience shortcut so callers don't need to
112
# build the tool object themselves; a raw dict is also unwrapped for
113
# backwards-compatibility with call-sites that used dict syntax.
114
edge_tool_kwargs = {}
115
if
"EdgeModelPath"
in
kwargs:
116
edge_tool_kwargs[
"ModelPath"
] = kwargs.pop(
"EdgeModelPath"
)
117
# Silently unwrap legacy dict-style: EdgeClassifierTool={"ModelPath": ...}
118
if
isinstance(kwargs.get(
"EdgeClassifierTool"
), dict):
119
edge_tool_kwargs.update(kwargs.pop(
"EdgeClassifierTool"
))
120
121
candidate_builder_kwargs = {}
122
for
key
in
(
"EdgeThreshold"
,
123
"OverlapThreshold"
,
124
"UseRecoveryComponents"
,
125
"SymmetrizeDirectedEdges"
,
126
"AddAllSegmentsRecoveryCandidate"
,
127
"KeepIsolatedSegments"
,
128
"MinCandidateSize"
):
129
if
key
in
kwargs:
130
candidate_builder_kwargs[key] = kwargs.pop(key)
131
132
if
isinstance(kwargs.get(
"CandidateBuilderTool"
), dict):
133
candidate_builder_kwargs.update(kwargs.pop(
"CandidateBuilderTool"
))
134
135
if
"EdgeClassifierTool"
not
in
kwargs:
136
kwargs[
"EdgeClassifierTool"
] = result.popToolsAndMerge(
137
SegmentEdgeClassifierToolCfg
(flags, **edge_tool_kwargs))
138
kwargs.setdefault(
"CandidateBuilderTool"
, result.popToolsAndMerge(
139
SegmentTrackCandidateBuilderToolCfg
(flags, **candidate_builder_kwargs)))
140
kwargs.setdefault(
"SegmentKey"
,
"MuonSegmentsFromR4"
)
141
kwargs.setdefault(
"CandidateDecoration"
,
"MuonSegmentsFromR4.trackCandidateIds"
)
142
alg = CompFactory.MuonML.SegmentEdgeInferenceAlg(name=name, **kwargs)
143
result.addEventAlgo(alg, primary=
True
)
144
return
result
145
146
147
def
DisplacedVertexInferenceToolCfg
(flags, name="DisplacedVertexInferenceTool", **kwargs):
148
"""Configure the DisplacedVertex graph-level ONNX inference tool.
149
The current DV ONNX export consumes raw graph tensors with the contract
150
x [N,7], edge_index [2,E], edge_attr [E,5], n_muon_nodes [1] -> logits [1]
151
"""
152
from
AthOnnxComps.OnnxRuntimeSessionConfig
import
OnnxRuntimeSessionToolCfg
153
154
result = ComponentAccumulator()
155
model_path = kwargs.pop(
"ModelPath"
,
"MuonInference/models/edge_class_dv_mu200.onnx"
)
156
157
result.merge(
MuonLearningOnnxRuntimeSvcCfg
(flags))
158
kwargs.setdefault(
"ModelSession"
, result.popToolsAndMerge(
159
OnnxRuntimeSessionToolCfg(flags, model_fname=model_path,
160
OnnxRuntimeSvc=result.getService(
"OnnxRuntimeSvc"
))))
161
kwargs.setdefault(
"InputNodeName"
,
"x"
)
162
kwargs.setdefault(
"InputEdgeIndexName"
,
"edge_index"
)
163
kwargs.setdefault(
"InputEdgeAttrName"
,
"edge_attr"
)
164
kwargs.setdefault(
"InputNMuonNodesName"
,
"n_muon_nodes"
)
165
kwargs.setdefault(
"OutputName"
,
"logits"
)
166
kwargs.setdefault(
"SingleOutputMode"
,
"logit"
)
167
if
"SpacePointKeys"
not
in
kwargs:
168
sp_containers = []
169
if
flags.Detector.GeometryMDT
or
flags.Detector.GeometryRPC
or
flags.Detector.GeometryTGC:
170
sp_containers.append(
"MuonSpacePoints"
)
171
elif
flags.Detector.GeometryMM
or
flags.Detector.GeometrysTGC:
172
sp_containers.append(
"NswSpacePoints"
)
173
kwargs.setdefault(
"SpacePointKeys"
, sp_containers)
174
kwargs.setdefault(
"UseBucketSegmentSelection"
,
True
)
175
kwargs.setdefault(
"MinTowerEnergyMeV"
, 1000.0)
176
kwargs.setdefault(
"MaxTowerSegmentDR"
, 0.4)
177
kwargs.setdefault(
"CaloRMaxMm"
, 4250.0)
178
kwargs.setdefault(
"CaloZMaxMm"
, 6500.0)
179
kwargs.setdefault(
"SectorModulo"
, 16)
180
kwargs.setdefault(
"RequireEdges"
,
False
)
181
tool = CompFactory.MuonML.DVInferenceToolBase(name, **kwargs)
182
result.setPrivateTools(tool)
183
return
result
184
185
186
def
DisplacedVertexCaloTowerCfg
(flags):
187
"""Configure the calorimeter reconstruction used by the DV training converter.
188
"""
189
result = ComponentAccumulator()
190
191
# Same reconstruction chain used by MuonBucketDumpConfig.CaloCellsDumperCfg.
192
from
CaloRec.CaloRecoConfig
import
CaloRecoCfg
193
result.merge(CaloRecoCfg(flags))
194
195
from
CaloRec.CaloTowerMakerConfig
import
CaloTowerMakerCfg
196
result.getPrimaryAndMerge(CaloTowerMakerCfg(flags))
197
198
return
result
199
200
201
def
DisplacedVertexInferenceAlgCfg
(flags, name="DisplacedVertexInferenceAlg", **kwargs):
202
"""Configure a runnable event-level DisplacedVertex inference algorithm."""
203
result = ComponentAccumulator()
204
do_calo_tower_build = kwargs.pop(
"DoCaloTowerBuild"
,
True
)
205
do_ml_bucket_filter = kwargs.pop(
"DoMLBucketFilter"
,
True
)
206
bucket_model_path = kwargs.pop(
"BucketModelPath"
,
None
)
207
bucket_threshold = kwargs.pop(
"BucketThreshold"
,
None
)
208
filtered_bucket_key = kwargs.pop(
"FilteredBucketKey"
,
"FilteredMlBuckets"
)
209
use_filtered_buckets_for_dv_graph = kwargs.pop(
"UseFilteredBucketsForDVGraph"
,
False
)
210
alg_output_level = kwargs.get(
"OutputLevel"
,
None
)
211
tool_kwargs = {}
212
for
key
in
(
213
"ModelPath"
,
214
"InputNodeName"
,
215
"InputEdgeIndexName"
,
216
"InputEdgeAttrName"
,
217
"InputNMuonNodesName"
,
218
"OutputName"
,
219
"SingleOutputMode"
,
220
"SegmentKey"
,
221
"SpacePointKeys"
,
222
"UseBucketSegmentSelection"
,
223
"TowerContainerKey"
,
224
"MinTowerEnergyMeV"
,
225
"MaxTowerSegmentDR"
,
226
"CaloRMaxMm"
,
227
"CaloZMaxMm"
,
228
"SectorModulo"
,
229
"RequireEdges"
,
230
"MaxEdges"
,
231
"FallbackToAllSegments"
,
232
"DebugDumpFirstNNodes"
,
233
"DebugDumpFirstNEdges"
,
234
"SpacePointKeys"
,
235
"UseBucketSegmentSelection"
,
236
"OutputLevel"
,
237
):
238
if
key
in
kwargs:
239
tool_kwargs[key] = kwargs.pop(key)
240
241
if
isinstance(kwargs.get(
"InferenceTool"
), dict):
242
tool_kwargs.update(kwargs.pop(
"InferenceTool"
))
243
244
tower_key = tool_kwargs.get(
"TowerContainerKey"
,
"CombinedTower"
)
245
if
do_calo_tower_build
and
tower_key:
246
result.merge(
DisplacedVertexCaloTowerCfg
(flags))
247
248
if
do_ml_bucket_filter:
249
bucket_filter_kwargs = {
250
"WriteSpacePointKey"
: filtered_bucket_key,
251
"ReadSpacePoints"
:
"MuonSpacePoints"
,
252
}
253
if
bucket_model_path
is
not
None
:
254
bucket_filter_kwargs[
"ModelPath"
] = bucket_model_path
255
if
bucket_threshold
is
not
None
:
256
bucket_filter_kwargs[
"ScoreThreshold"
] = bucket_threshold
257
bucket_tool = result.popToolsAndMerge(
258
GraphBucketFilterToolCfg
(flags, **bucket_filter_kwargs)
259
)
260
result.merge(
261
GraphInferenceAlgCfg
(
262
flags,
263
name=
"DVBucketPrefilterAlg"
,
264
InferenceTools=[bucket_tool],
265
)
266
)
267
if
use_filtered_buckets_for_dv_graph:
268
tool_kwargs.setdefault(
"SpacePointKeys"
, [filtered_bucket_key])
269
tool_kwargs.setdefault(
"UseBucketSegmentSelection"
,
True
)
270
271
if
"InferenceTool"
not
in
kwargs:
272
kwargs[
"InferenceTool"
] = result.popToolsAndMerge(
273
DisplacedVertexInferenceToolCfg
(flags, **tool_kwargs)
274
)
275
276
if
alg_output_level
is
not
None
:
277
kwargs[
"OutputLevel"
] = alg_output_level
278
279
kwargs.setdefault(
"ScoreDecoration"
,
"EventInfo.dv_score"
)
280
kwargs.setdefault(
"RawOutputDecoration"
,
"EventInfo.dv_rawOutput"
)
281
kwargs.setdefault(
"PassDecoration"
,
"EventInfo.dv_pass"
)
282
kwargs.setdefault(
"NNodesDecoration"
,
"EventInfo.dv_nNodes"
)
283
kwargs.setdefault(
"NEdgesDecoration"
,
"EventInfo.dv_nEdges"
)
284
alg = CompFactory.MuonML.DVInferenceAlg(name=name, **kwargs)
285
result.addEventAlgo(alg, primary=
True
)
286
return
result
InferenceConfig.DisplacedVertexCaloTowerCfg
DisplacedVertexCaloTowerCfg(flags)
Definition
InferenceConfig.py:186
InferenceConfig.SegmentEdgeInferenceAlgCfg
SegmentEdgeInferenceAlgCfg(flags, name="SegmentEdgeInferenceAlg", **kwargs)
Definition
InferenceConfig.py:109
InferenceConfig.SegmentTrackCandidateBuilderToolCfg
SegmentTrackCandidateBuilderToolCfg(flags, name="SegmentTrackCandidateBuilderTool", **kwargs)
Definition
InferenceConfig.py:92
InferenceConfig.GraphInferenceAlgCfg
GraphInferenceAlgCfg(flags, name="GraphInferenceAlg", **kwargs)
Definition
InferenceConfig.py:18
InferenceConfig.GraphSPFilterToolCfg
GraphSPFilterToolCfg(flags, name="GraphSPFilterTool", **kwargs)
Definition
InferenceConfig.py:24
InferenceConfig.SegmentEdgeClassifierToolCfg
SegmentEdgeClassifierToolCfg(flags, name="SegmentEdgeClassifierTool", **kwargs)
Definition
InferenceConfig.py:69
InferenceConfig.DisplacedVertexInferenceAlgCfg
DisplacedVertexInferenceAlgCfg(flags, name="DisplacedVertexInferenceAlg", **kwargs)
Definition
InferenceConfig.py:201
InferenceConfig.MuonLearningOnnxRuntimeSvcCfg
MuonLearningOnnxRuntimeSvcCfg(flags, name="OnnxRuntimeSvc", **kwargs)
Definition
InferenceConfig.py:10
InferenceConfig.GraphBucketFilterToolCfg
GraphBucketFilterToolCfg(flags, name="GraphBucketFilterTool", **kwargs)
Definition
InferenceConfig.py:36
InferenceConfig.DisplacedVertexInferenceToolCfg
DisplacedVertexInferenceToolCfg(flags, name="DisplacedVertexInferenceTool", **kwargs)
Definition
InferenceConfig.py:147
Generated on
for ATLAS Offline Software by
1.17.0