ATLAS Offline Software
Loading...
Searching...
No Matches
muonBucketInference.py
Go to the documentation of this file.
1# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
3import os
4import logging
5
6# Suppress ONNX Runtime warnings at Python logging level before Athena initialization
7logging.getLogger("onnxruntime").setLevel(logging.ERROR)
8
9# Set environment variable for ONNX Runtime before imports (attempt early suppression)
10os.environ["ORT_LOGGING_LEVEL"] = "3" # 3 = ERROR
11
12if __name__ == "__main__":
13 from MuonGeoModelTestR4.testGeoModel import SetupArgParser, MuonPhaseIITestDefaults
14 parser = SetupArgParser()
15 from MuonInference.InferenceConfig import (
16 DEFAULT_BUCKET_MODEL_PATH,
17 DEFAULT_BUCKET_SCORE_THRESHOLD,
18 DEFAULT_BUCKET_SINGLE_OUTPUT_MODE,
19 )
20 parser.set_defaults(nEvents = -1)
21 parser.set_defaults(outRootFile="InferenceHoughTest.root")
22 parser.set_defaults(inputFile=MuonPhaseIITestDefaults.RDO_R4)
23 parser.set_defaults(defaultGeoFile="RUN4")
24
25 parser.add_argument("--doPerfMon", help="If set to true, full perfmonMT is enabled",
26 default=False, action='store_true')
27 parser.add_argument("--use-cpu", action="store_true", default=False, help="Use CPU for ONNX inference")
28 parser.add_argument("--athenaDebug", action="store_true", default=False,
29 help="Enable DEBUG verbosity for bucket inference components in MessageSvc")
30 parser.add_argument("--athenaVerbose", action="store_true", default=False,
31 help="Enable VERBOSE verbosity for bucket inference components in MessageSvc")
32 parser.add_argument("--bucket-model-path", dest="bucket_model_path", default=DEFAULT_BUCKET_MODEL_PATH,
33 help="Absolute path (or PathResolver key) for the bucket ONNX model")
34 parser.add_argument("--score-threshold", type=float, default=DEFAULT_BUCKET_SCORE_THRESHOLD, dest="score_threshold",
35 help="Keep bucket if single-output score > threshold (default: 0.2)")
36 parser.add_argument("--output-name", default="logits", dest="output_name")
37 score_mode = parser.add_mutually_exclusive_group()
38 score_mode.add_argument("--single-output-mode", choices=("logit", "prob"), default=DEFAULT_BUCKET_SINGLE_OUTPUT_MODE, dest="single_output_mode",
39 help="Scalar ONNX-output interpretation. 'logit' applies sigmoid before thresholding.")
40 score_mode.add_argument("--is-logit", action="store_const", const="logit", dest="single_output_mode", help="alias for --single-output-mode logit.")
41 score_mode.add_argument("--is-prob", action="store_const", const="prob", dest="single_output_mode", help="alias for --single-output-mode prob.")
42 parser.add_argument("--bucket-debug-dump-file", default="", dest="bucket_debug_dump_file",
43 help=("Optional JSONL output file with Athena-side bucket ONNX."))
44 parser.add_argument("--bucket-debug-dump-max-events", type=int, default=0, dest="bucket_debug_dump_max_events",
45 help=("Maximum number of events to write to --bucket-debug-dump-file."))
46 parser.add_argument("--bucket-print-labels", action="store_true", default=False, dest="bucket_print_labels",
47 help=("Print per-event good-bucket efficiency using the training label."))
48 parser.add_argument("--bucket-label-print-first-n-buckets", type=int, default=20, dest="bucket_label_print_first_n_buckets",
49 help=("When --bucket-print-labels is enabled, print detailed label/decision."))
50 parser.add_argument("--bucket-label-segment-key", default="MuonSegmentsFromR4", dest="bucket_label_segment_key",
51 help=("Optional xAOD::MuonSegmentContainer key used for the bucket_segments."))
52
53 args = parser.parse_args()
54
55 from MuonGeoModelTestR4.testGeoModel import setupGeoR4TestCfg
56 from MuonConfig.MuonConfigUtils import executeTest, setupHistSvcCfg
57 from AthenaConfiguration.AllConfigFlags import initConfigFlags
58
59 flags = initConfigFlags()
60 flags.PerfMon.doFullMonMT = getattr(args, "doPerfMon", False)
61 if args.athenaDebug or args.athenaVerbose:
62 flags.Common.MsgSuppression = False
63
64 from AthOnnxComps.OnnxRuntimeFlags import OnnxRuntimeType
65 # Use command line argument if provided, otherwise default to True
66 use_gpu_requested = not args.use_cpu
67 gpu_available = False
68 try:
69 import onnxruntime as ort
70 gpu_available = "CUDAExecutionProvider" in ort.get_available_providers()
71 except Exception:
72 try:
73 import torch
74 gpu_available = torch.cuda.is_available()
75 except Exception:
76 gpu_available = False
77 if use_gpu_requested and gpu_available:
78 flags.AthOnnx.ExecutionProvider = OnnxRuntimeType.CUDA
79 else:
80 flags.AthOnnx.ExecutionProvider = OnnxRuntimeType.CPU
81
82 flags, cfg = setupGeoR4TestCfg(args,flags)
83
84 from MuonConfig.MuonDataPrepConfig import xAODUncalibMeasPrepCfg
85 cfg.merge(xAODUncalibMeasPrepCfg(flags))
86
87 from MuonSpacePointFormation.SpacePointFormationConfig import MuonSpacePointFormationCfg
88 cfg.merge(MuonSpacePointFormationCfg(flags))
89
90 from MuonPatternRecognitionAlgs.MuonPatternRecognitionConfig import MuonPatternRecognitionCfg
91
92
93 sample_is_mc = bool(flags.Input.isMC)
94 use_truth_labels = bool(args.bucket_print_labels and sample_is_mc)
95 use_segment_labels = bool(args.bucket_print_labels and (not sample_is_mc))
96
97 if use_segment_labels and not args.bucket_label_segment_key:
98 raise RuntimeError(
99 "--bucket-print-labels was requested for recorded data, but "
100 "--bucket-label-segment-key is empty. Set it to MuonSegmentsFromR4 "
101 "or disable label printing."
102 )
103
104 build_label_segments_first = bool(use_segment_labels)
105
106 if build_label_segments_first:
107 cfg.merge(MuonPatternRecognitionCfg(flags))
108
109 from MuonInference.InferenceConfig import GraphBucketFilterToolCfg, GraphInferenceAlgCfg
110 output_level = 1 if args.athenaVerbose else (2 if args.athenaDebug else 3)
111
112 bucket_tool_kwargs = dict(
113 ModelPath=args.bucket_model_path,
114 ScoreThreshold=args.score_threshold,
115 OutputName=args.output_name,
116 SingleOutputMode=args.single_output_mode,
117 DebugDumpFile=args.bucket_debug_dump_file,
118 DebugDumpMaxEvents=args.bucket_debug_dump_max_events,
119 PrintLabels=args.bucket_print_labels,
120 LabelPrintFirstNBuckets=args.bucket_label_print_first_n_buckets,
121 OutputLevel=output_level,
122 )
123
124 if args.bucket_print_labels:
125 if use_truth_labels:
126 from MuonPatternRecognitionTest.PatternTestConfig import PatternVisualizationToolCfg
127 bucket_tool_kwargs["LabelVisualizationTool"] = cfg.popToolsAndMerge(
128 PatternVisualizationToolCfg(flags, CanvasLimits=0))
129 print("Bucket label mode: MC input sample -> label = bucket with truth muons only")
130 elif use_segment_labels:
131 bucket_tool_kwargs["LabelSegmentKey"] = args.bucket_label_segment_key
132 print("Bucket label mode: recorded-data input sample -> label = bucket_segments > 0 "
133 f"using {args.bucket_label_segment_key}")
134
135 bucketTool = cfg.popToolsAndMerge(GraphBucketFilterToolCfg(flags, **bucket_tool_kwargs))
136 cfg.merge(GraphInferenceAlgCfg(flags, InferenceTools=[bucketTool]))
137
138 if not build_label_segments_first:
139 cfg.merge(MuonPatternRecognitionCfg(flags))
140 cfg.getEventAlgo("MuonEtaHoughTransformAlg").SpacePointContainer = "FilteredMlBuckets"
141
142 cfg.merge(setupHistSvcCfg( flags, outFile=args.outRootFile,
143 outStream="MuonEtaHoughTransformTest"))
144
145 from MuonPatternRecognitionTest.PatternTestConfig import MuonHoughTransformTesterCfg, PatternVisualizationToolCfg
146
147 cfg.merge(MuonHoughTransformTesterCfg( flags,
148 VisualizationTool = cfg.popToolsAndMerge(PatternVisualizationToolCfg(flags, CanvasLimits =0))))
149
150 executeTest(cfg)
void print(char *figname, TCanvas *c1)