ATLAS Offline Software
Loading...
Searching...
No Matches
muonEdgeRecoChain.py
Go to the documentation of this file.
1#!/usr/bin/env python
2# Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3# End-to-end test: segment edge inference -> ML segment filter -> ML-assisted track seeding.
4
5import argparse
6
7
8def main(args):
9 from MuonGeoModelTestR4.testGeoModel import setupGeoR4TestCfg
10 from MuonConfig.MuonConfigUtils import executeTest, setupHistSvcCfg
11 from AthenaConfiguration.AllConfigFlags import initConfigFlags
12 flags = initConfigFlags()
13 flags.PerfMon.doFullMonMT = not args.noPerfMon
14 flags.PerfMon.OutputJSON = "perfmonmt_MuonR4Reco.json"
15 flags.Trigger.Muon.useNewRegionSelector = False
16
17 run_edge_classifier = not args.skip_onnx
18 run_ml_seeder = args.useMlSeeder and run_edge_classifier
19 filter_segment_container = args.filterSegmentsWithoutMlConnections and run_edge_classifier
20 filtered_segment_key = "MsSegmentsMlConnected"
21
22 if args.skip_onnx and args.useMlSeeder:
23 print("INFO: --skip-onnx requested. Switching to the standard seeder for the non-ONNX baseline.")
24
25 if args.athenaDebug:
26 flags.Exec.DebugMessageComponents = [
27 "SegmentEdgeInferenceAlg",
28 "SegmentEdgeInferenceAlg.SegmentEdgeClassifierTool",
29 "SegmentEdgeInferenceAlg.SegmentEdgeClassifierTool.OnnxRuntimeSessionToolCPU",
30 "SegmentEdgeInferenceAlg.SegmentEdgeClassifierTool.OnnxRuntimeSessionToolCUDA",
31 "MSTrackFinderAlg.MlMsTrackSeeder",
32 ]
33
34 from AthOnnxComps.OnnxRuntimeFlags import OnnxRuntimeType
35 flags.AthOnnx.ExecutionProvider = OnnxRuntimeType.CUDA if run_edge_classifier else OnnxRuntimeType.CPU
36
37 flags, cfg = setupGeoR4TestCfg(args, flags)
38
39 if not args.skipTrackTester:
40 cfg.merge(setupHistSvcCfg(flags, outFile=args.outRootFile,
41 outStream="MuonTrackTester"))
42
43 output_level = 1 if args.athenaDebug else 3
44
45 from MuonConfig.ReconstructionConfigR4 import MuonReconstructionConfig
46 cfg.merge(MuonReconstructionConfig(flags))
47
48 if run_edge_classifier:
49 if args.truthDiagnostics and not flags.Input.isMC:
50 print("WARNING: --truthDiagnostics requested on non-MC input.")
51 from MuonInference.InferenceConfig import SegmentEdgeInferenceAlgCfg
52 edge_inference_kwargs = {
53 "EdgeClassifierTool": {
54 "ModelPath": args.edgeModel,
55 "ReadSpacePoints": "MuonSpacePoints",
56 # These cuts run before ONNX
57 "MaxSegmentsPerBucket": args.maxSegmentsPerBucket,
58 "MaxEdgesPerNodeBeforeInference": 6,
59 "MaxEdgesPerTargetChamberBeforeInference": args.maxEdgesPerTargetChamber,
60 "EnableTruthDiagnostics": args.truthDiagnostics,
61 },
62 "PairGateDecoration": "MsSegments.mlTrackComponent",
63 "PairGateThreshold": args.edgeThreshold,
64 "MaxEdgesPerNodePerLayer": args.maxEdgesPerLayer,
65 # One anchor per component: the innermost segment with the strongest cross-layer edge
66 "SeedAnchorsPerComponent": 1,
67 "AnchorInnermostLayer": True,
68 "KeepBestSegmentPerChamber": not args.keepAllSegmentsPerChamber,
69 "OutputLevel": output_level,
70 }
71 if filter_segment_container:
72 edge_inference_kwargs["FilteredSegmentKey"] = filtered_segment_key
73 cfg.merge(SegmentEdgeInferenceAlgCfg(flags, **edge_inference_kwargs))
74
75 ms_track_finder = cfg.getEventAlgo("MSTrackFinderAlg")
76 ms_track_finder.OutputLevel = 3
77 if run_ml_seeder:
78 from MuonTrackFindingAlgs.TrackFindingConfig import MsTrackSeedingToolCfg, SegmentSelectorCfg
79 from AthenaConfiguration.ComponentFactory import CompFactory
80 baseline_seeder = cfg.popToolsAndMerge(MsTrackSeedingToolCfg(flags))
81 ms_track_finder.SeedingTool = CompFactory.MuonR4.MlMsTrackSeeder(
82 "MlMsTrackSeeder",
83 BaselineSeeder=baseline_seeder,
84 SegmentContainer="MsSegments",
85 CandidateDecoration="mlTrackComponent",
86 SegmentSelectionTool=cfg.popToolsAndMerge(SegmentSelectorCfg(flags)),
87 TwoSegmentMinComponentScore=args.mlTwoSegMinScore,
88 ExtraClusterSeeds=args.mlExtraClusterSeeds,
89 ExtraClusterMinScore=args.mlExtraClusterMinScore,
90 InnerPointingMaxDeg=args.mlInnerPointingMaxDeg,
91 InnerRescueWindow=args.mlInnerRescueWindow,
92 InnerRescueMaxDeg=args.mlInnerRescueMaxDeg,
93 VariantSeeds=args.mlVariantSeeds,
94 VariantMinLayers=args.mlVariantMinLayers,
95 VariantMaxPointingDeg=args.mlVariantMaxPointingDeg,
96 VariantMinScore=args.mlVariantMinScore,
97 EnableTruthDiagnostics=args.truthDiagnostics and flags.Input.isMC,
98 OutputLevel=2 if args.athenaDebug else 3,
99 )
100 elif filter_segment_container:
101 ms_track_finder.SeedingTool.SegmentContainer = filtered_segment_key
102
103 if not args.skipTrackTester:
104 from MuonTrackFindingTest.MsTrackFindingTester import MsTrackTesterCfg
105 cfg.merge(MsTrackTesterCfg(flags, scheduleLegacy=False, outFile=args.outRootFile))
106
107 cfg.printConfig(withDetails=True, summariseProps=True)
108 executeTest(cfg)
109
110
111if __name__ == "__main__":
112 from MuonGeoModelTestR4.testGeoModel import SetupArgParser, MuonPhaseIITestDefaults
113 parser = SetupArgParser()
114 parser.set_defaults(nEvents=-1)
115 parser.set_defaults(inputFile=MuonPhaseIITestDefaults.HITS_PG_R3)
116 parser.set_defaults(outRootFile="EdgeRecoChain.root")
117 parser.add_argument("--edgeModel", help="Segment edge classifier ONNX model")
118 parser.add_argument("--athenaDebug", action="store_true",
119 help="Enable Athena DEBUG verbosity for inference and seeding components")
120 parser.add_argument("--truthDiagnostics", action="store_true", default=False,
121 help="MC-only: DEBUG-log the truth diagnostics of the edge selection and of the seeding")
122 parser.add_argument("--noPerfMon", default=False, action="store_true",
123 help="Disable performance monitoring")
124 parser.add_argument("--edgeThreshold", type=float, default=0.01,
125 help="Minimum edge probability used to form ML track components (default: 0.01)")
126 parser.add_argument("--filterSegmentsWithoutMlConnections", action=argparse.BooleanOptionalAction,
127 default=True,
128 help="Pass MSTrackFinderAlg a VIEW containing only segments incident to a "
129 "selected ML edge (default: on)")
130 parser.add_argument("--useMlSeeder", dest="useMlSeeder", action="store_true", default=True,
131 help="Use the ML-assisted seeder (default)")
132 parser.add_argument("--useStandardSeeder", dest="useMlSeeder", action="store_false",
133 help="Use the standard seeder")
134 parser.add_argument("--mlTwoSegMinScore", type=float, default=0.3,
135 help="ML seeder: keep a 2-segment seed only if its component's strongest cross-layer "
136 "ML edge reaches this score; 0 disables (default: 0.3)")
137 parser.add_argument("--mlExtraClusterSeeds", type=int, default=2,
138 help="ML seeder: after the first window seed of a component, build up to this many "
139 "further window seeds from the segments not yet covered; 0 disables (default: 2)")
140 parser.add_argument("--mlExtraClusterMinScore", type=float, default=0.8,
141 help="ML seeder: an extra cluster seed needs a segment whose strongest selected "
142 "cross-layer ML edge reaches this score (default: 0.8)")
143 parser.add_argument("--mlInnerPointingMaxDeg", type=float, default=2.,
144 help="ML seeder: drop endcap inner segments whose |theta(dir)-theta(pos)| exceeds this "
145 "value [deg] (not pointing to the IP) from the seeds; 0 disables (default: 2)")
146 parser.add_argument("--mlInnerRescueWindow", type=float, default=0.,
147 help="ML seeder: fill a missing Inner layer with the closest IP-pointing inner segment "
148 "of any component within this distance [mm]; 0 disables (default: 0)")
149 parser.add_argument("--mlInnerRescueMaxDeg", type=float, default=1.,
150 help="ML seeder: pointing cut [deg] of the segment used by --mlInnerRescueWindow (default: 1)")
151 parser.add_argument("--mlVariantSeeds", action=argparse.BooleanOptionalAction, default=True,
152 help="ML seeder: emit a second, different seed (runner-up segments) for seeds passing "
153 "the --mlVariant* gates, as a fallback if the first fit fails (default: on)")
154 parser.add_argument("--mlVariantMinLayers", type=int, default=3,
155 help="ML seeder: variant seeds only for seeds with at least this many station layers (default: 3)")
156 parser.add_argument("--mlVariantMaxPointingDeg", type=float, default=1.,
157 help="ML seeder: variant seeds only for endcap seeds whose inner segment points to the IP "
158 "within this value [deg] (default: 1)")
159 parser.add_argument("--mlVariantMinScore", type=float, default=0.8,
160 help="ML seeder: variant seeds only for components whose strongest cross-layer ML edge "
161 "reaches this score; 0 disables (default: 0.8)")
162 parser.add_argument("--maxEdgesPerLayer", type=int, default=1,
163 help="After ONNX, each segment nominates its best N edges towards each layer instead "
164 "of its best 2 edges overall (mutual selection unchanged); 0 keeps the global "
165 "top-2 (default: 1)")
166 parser.add_argument("--maxEdgesPerTargetChamber", type=int, default=1,
167 help="Before ONNX, each segment keeps at most this many geometrical neighbours "
168 "in one target chamber; 0 keeps all (default: 1)")
169 parser.add_argument("--maxSegmentsPerBucket", type=int, default=0,
170 help="Keep at most this many best duplicate segments in each "
171 "(sector,chamber,eta) bucket before ONNX; 0 keeps all (default: 0)")
172 parser.add_argument("--keepAllSegmentsPerChamber", action="store_true", default=True,
173 help="Keep all ML component segments from a chamber (default)")
174 parser.add_argument("--disableBucketFilter", action="store_true", default=True,
175 help="No effect: the bucket filter is not part of this chain (kept so that "
176 "existing commands still run)")
177 parser.add_argument("--skipTrackTester", action="store_true", default=False,
178 help="Do not write the MsTrackValidTest validation tree")
179 parser.add_argument("--skip-onnx", action="store_true", default=False,
180 help="Skip the edge classifier: non-ML baseline with the standard seeder")
181
182 args = parser.parse_args()
183
184 if not args.skip_onnx and not args.edgeModel:
185 parser.error("--edgeModel is required unless --skip-onnx is given")
186 main(args)
void print(char *figname, TCanvas *c1)
int main()
Definition hello.cxx:18