ATLAS Offline Software
Loading...
Searching...
No Matches
SegmentEdgeInferenceAlg.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4#ifndef MUONINFERENCE_SEGMENTEDGEINFERENCEALG_H
5#define MUONINFERENCE_SEGMENTEDGEINFERENCEALG_H
6
10#include "Gaudi/Property.h"
16
17#include <array>
18#include <atomic>
19#include <cstdint>
20#include <unordered_map>
21#include <unordered_set>
22#include <vector>
23
24namespace MuonML {
26 public:
27 using AthReentrantAlgorithm::AthReentrantAlgorithm;
28 StatusCode initialize() override;
29 StatusCode execute(const EventContext& ctx) const override;
30
32 StatusCode finalize() override;
33 private:
37 const xAOD::MuonSegmentContainer& segments,
38 const SegmentEdgeGraph& graph,
39 const std::unordered_map<std::uint64_t, float>& pairProbability,
40 const std::vector<unsigned char>& thresholded,
41 const std::vector<std::uint8_t>& keptNode,
42 const std::vector<unsigned char>& nodeDropReason) const;
43
46 // grouping (clean/mixed/fragmented).
48 const std::unordered_map<std::int32_t, std::unordered_set<unsigned>>& muonComponents,
49 const std::unordered_map<std::int32_t, bool>& muonEverMixed,
50 const std::unordered_map<std::int32_t, double>& truthIdToAbsEta) const;
51
56 this, "PairGateDecoration", "MsSegments.mlTrackComponent"};
57
61 this, "ComponentScoreDecoration", "MsSegments.mlComponentScore"};
63 this, "FilteredSegmentKey", "",
64 "Optional VIEW container containing only segments incident to a "
65 "post-classifier selected edge; empty disables the output"};
66 Gaudi::Property<float> m_pairGateThreshold{
67 this, "PairGateThreshold", 0.5f,
68 "Minimum edge probability used to form ML track components"};
69 Gaudi::Property<unsigned int> m_maxEdgesPerNode{
70 this, "MaxEdgesPerNode", 2,
71 "Keep at most this many highest-score neighbours per segment when forming the ML path graph; zero keeps all"};
72 Gaudi::Property<unsigned int> m_maxEdgesPerNodePerLayer{
73 this, "MaxEdgesPerNodePerLayer", 0,
74 "If > 0, each segment nominates its this-many highest-score edges towards EACH layer (Inner, "
75 "Middle, Outer, Extended, ...) instead of its MaxEdgesPerNode best edges overall; zero keeps "
76 "the global top-K"};
77 Gaudi::Property<bool> m_useDegreeCappedComponents{
78 this, "UseDegreeCappedComponents", false,
79 "Use a global greedy degree cap instead of the mutual top-K path graph"};
80 Gaudi::Property<bool> m_requireMutualTopKEdges{
81 this, "RequireMutualTopKEdges", true,
82 "Retain an ML association only when both endpoint segments rank it in their top MaxEdgesPerNode scores"};
83 Gaudi::Property<bool> m_recoverOrphanNodes{
84 this, "RecoverOrphanNodes", true,
85 "For a thresholded node without a mutual top-K edge, retain its best one-sided top-K association"};
86 Gaudi::Property<unsigned int> m_seedAnchorsPerComponent{
87 this, "SeedAnchorsPerComponent", 0,
88 "Number of highest-score segments that may seed each ML component; zero keeps every retained segment"};
89 Gaudi::Property<bool> m_anchorInnermostLayer{
90 this, "AnchorInnermostLayer", false,
91 "Restrict seed anchors to inner segment(s); with SeedAnchorsPerComponent > 0 keep only "
92 "the inner segment(s) with the strongest selected edge towards another layer"};
93 Gaudi::Property<bool> m_keepBestSegmentPerChamber{
94 this, "KeepBestSegmentPerChamber", true,
95 "Keep only the ML-best segment in each chamber within a component"};
96 Gaudi::Property<unsigned int> m_minSegmentsPerComponent{
97 this, "MinSegmentsPerComponent", 2,
98 "Discard ML components with fewer retained segments"};
99 ToolHandle<ISegmentEdgeClassifierTool> m_edgeClassifier{this, "EdgeClassifierTool", "MuonML::SegmentEdgeClassifierTool/SegmentEdgeClassifierTool"};
104
106 mutable std::atomic<std::size_t> m_sumGraphNodes{0};
107 mutable std::atomic<std::size_t> m_sumThresholdedNodes{0};
108 mutable std::atomic<std::size_t> m_sumMutualTopKPairs{0};
109 mutable std::atomic<std::size_t> m_sumOneSidedTopKPairs{0};
110 mutable std::atomic<std::size_t> m_sumOrphanRecoveryPairs{0};
111 mutable std::atomic<std::size_t> m_sumTopologyNodes{0};
112 mutable std::atomic<std::size_t> m_sumRetainedNodes{0};
113 mutable std::atomic<std::size_t> m_sumChamberSuppressedNodes{0};
114 mutable std::atomic<std::size_t> m_sumNodesRejectedByMinComponent{0};
115 mutable std::atomic<std::size_t> m_sumRejectedComponents{0};
116 mutable std::atomic<std::size_t> m_sumComponentsKept{0};
117
118 // Job-summed truth-vs-background funnel (see execute()); only touched
119 // when EnableTruthDiagnostics && msgLvl(MSG::DEBUG). "Truth" segment
120 // means getTruthMatchedParticle(seg) != nullptr (SegmentDumperAlg's
121 // m_segmentHasTruth criterion). A "true edge" is a candidate pair whose
122 // two segments share the same truth-particle index.
123 mutable std::atomic<std::size_t> m_sumInputTruthSegments{0};
124 mutable std::atomic<std::size_t> m_sumInputBkgSegments{0};
125 mutable std::atomic<std::size_t> m_sumOnnxTruthSegments{0};
126 mutable std::atomic<std::size_t> m_sumOnnxBkgSegments{0};
127 mutable std::atomic<std::size_t> m_sumRetainedTruthSegments{0};
128 mutable std::atomic<std::size_t> m_sumRetainedBkgSegments{0};
129 mutable std::atomic<std::size_t> m_sumTrueEdgesTotal{0};
130 mutable std::atomic<std::size_t> m_sumTrueEdgesPassed{0};
133 mutable std::array<std::atomic<std::size_t>, 2> m_sumTrueCrossLayerEdges ATLAS_THREAD_SAFE{};
134 mutable std::array<std::atomic<std::size_t>, 2> m_sumTrueCrossLayerSelected ATLAS_THREAD_SAFE{};
135 mutable std::atomic<std::size_t> m_sumBkgEdgesTotal{0};
136 mutable std::atomic<std::size_t> m_sumBkgEdgesPassed{0};
137
142 static constexpr std::size_t kCategories = 11;
143 static constexpr std::size_t kColumns = 5;
144 std::array<std::atomic<std::size_t>, kCategories * kColumns> category{};
145 std::array<std::atomic<std::size_t>, 5> scoreBin{};
146 std::array<std::atomic<std::size_t>, 2> sectorDelta{};
147 std::array<std::atomic<std::size_t>, 4> layerPair{};
148 std::array<std::atomic<std::size_t>, 4> muonSegments{};
149 std::array<std::atomic<std::size_t>, 3> precisionHits{};
150 std::array<std::atomic<std::size_t>, 4> muonsSeedable{};
151 std::array<std::atomic<std::size_t>, 4> muonsSeedLost{};
152 };
153
155 mutable std::atomic<bool> m_warnedMissingToolDiagnostics{false};
156
162 static constexpr std::size_t kSizeBins = 6; // 2, 3, 4, 5-9, 10-19, 20+
163 static constexpr std::size_t kColumns = 4; // all, barrel, transition, endcap
164 static constexpr std::size_t kScoreBins = 5; // <0.05, 0.05-0.1, 0.1-0.3, 0.3-0.5, >=0.5
165 static constexpr std::size_t kLayerBins = 4; // 1, 2, 3, 4+ distinct layers
166 std::array<std::atomic<std::size_t>, 3> componentsByOutcome{};
167 std::array<std::atomic<std::size_t>, kSizeBins> componentSizeHist{};
169 std::array<std::atomic<std::size_t>, 3 * kScoreBins> scoreByOutcome{};
170 std::array<std::atomic<std::size_t>, 3 * kSizeBins> sizeByOutcome{};
171 std::array<std::atomic<std::size_t>, 3 * kLayerBins> layersByOutcome{};
173 static constexpr std::size_t kCrossScoreBins = 6; // <0.05, 0.05-0.1, 0.1-0.3, 0.3-0.5, 0.5-0.8, >=0.8
174 static constexpr std::size_t kCrossEdgeBins = 4; // 0, 1, 2, 3+ selected cross-layer edges
175 std::array<std::atomic<std::size_t>, 3 * kCrossScoreBins> crossScoreByOutcome{};
176 std::array<std::atomic<std::size_t>, 3 * kCrossEdgeBins> crossEdgesByOutcome{};
177 std::atomic<std::size_t> weakCleanWithOther{0};
178 std::atomic<std::size_t> weakCleanAlone{0};
179 std::atomic<std::size_t> mixedComponentSegments{0};
180 std::array<std::atomic<std::size_t>, kColumns * 3> muonOutcome{};
181 std::atomic<std::uint64_t> worstMixedPacked{0};
182 };
183
185 };
186}
187#endif
DataVector adapter that acts like it holds const pointers.
Property holding a SG store/key/clid from which a ReadHandle is made.
Property holding a SG store/key/clid/attr name from which a WriteDecorHandle is made.
Property holding a SG store/key/clid from which a WriteHandle is made.
Define macros for attributes used to control the static checker.
An algorithm that can be simultaneously executed in multiple threads.
std::atomic< std::size_t > m_sumOnnxBkgSegments
std::atomic< std::size_t > m_sumChamberSuppressedNodes
Gaudi::Property< bool > m_keepBestSegmentPerChamber
void classifyGroupPurity(const std::unordered_map< std::int32_t, std::unordered_set< unsigned > > &muonComponents, const std::unordered_map< std::int32_t, bool > &muonEverMixed, const std::unordered_map< std::int32_t, double > &truthIdToAbsEta) const
MC-only: given the per-muon component memberships and mixed-status gathered while the per-component c...
std::atomic< std::size_t > m_sumRetainedNodes
Gaudi::Property< bool > m_anchorInnermostLayer
SG::WriteDecorHandleKey< xAOD::MuonSegmentContainer > m_pairGateDecorKey
Per-segment payload consumed by MlMsTrackSeeder: [componentId, anchorRank + 1] Empty means that the s...
Gaudi::Property< bool > m_useDegreeCappedComponents
std::atomic< std::size_t > m_sumOrphanRecoveryPairs
ToolHandle< ISegmentEdgeClassifierTool > m_edgeClassifier
StatusCode finalize() override
Log of the post-ONNX rank/mutuality and min-component-size selection.
Gaudi::Property< unsigned int > m_maxEdgesPerNode
std::atomic< std::size_t > m_sumThresholdedNodes
std::atomic< std::size_t > m_sumRetainedBkgSegments
std::array< std::atomic< std::size_t >, 2 > m_sumTrueCrossLayerEdges ATLAS_THREAD_SAFE
True cross-layer edges above PairGateThreshold, total and kept by the selection; barrel / endcap Ever...
Gaudi::Property< bool > m_requireMutualTopKEdges
std::atomic< std::size_t > m_sumOneSidedTopKPairs
std::atomic< std::size_t > m_sumInputBkgSegments
void classifyLostTruthSegments(const xAOD::MuonSegmentContainer &segments, const SegmentEdgeGraph &graph, const std::unordered_map< std::uint64_t, float > &pairProbability, const std::vector< unsigned char > &thresholded, const std::vector< std::uint8_t > &keptNode, const std::vector< unsigned char > &nodeDropReason) const
MC-only: classify every truth-labeled input segment that did not make it into the filtered container ...
std::atomic< std::size_t > m_sumTrueEdgesPassed
bool m_truthDiagEnabled
Whether truth-particle matching is available/enabled this job.
std::atomic< std::size_t > m_sumBkgEdgesPassed
StatusCode execute(const EventContext &ctx) const override
std::atomic< std::size_t > m_sumBkgEdgesTotal
std::atomic< std::size_t > m_sumGraphNodes
Job-summed post-ONNX selection counters (see execute()).
Gaudi::Property< unsigned int > m_minSegmentsPerComponent
std::atomic< std::size_t > m_sumOnnxTruthSegments
std::atomic< std::size_t > m_sumInputTruthSegments
std::atomic< std::size_t > m_sumNodesRejectedByMinComponent
std::atomic< std::size_t > m_sumTrueEdgesTotal
std::atomic< std::size_t > m_sumRetainedTruthSegments
SG::WriteHandleKey< ConstDataVector< xAOD::MuonSegmentContainer > > m_filteredSegmentKey
Gaudi::Property< bool > m_recoverOrphanNodes
std::atomic< std::size_t > m_sumMutualTopKPairs
Gaudi::Property< unsigned int > m_maxEdgesPerNodePerLayer
SG::WriteDecorHandleKey< xAOD::MuonSegmentContainer > m_componentScoreDecorKey
Per-segment ML scores for MlMsTrackSeeder: [strongest selected cross-layer edge of the segment's comp...
std::atomic< std::size_t > m_sumRejectedComponents
SG::ReadHandleKey< xAOD::MuonSegmentContainer > m_segmentKey
Gaudi::Property< unsigned int > m_seedAnchorsPerComponent
Gaudi::Property< float > m_pairGateThreshold
std::atomic< std::size_t > m_sumTopologyNodes
std::atomic< std::size_t > m_sumComponentsKept
Property holding a SG store/key/clid from which a ReadHandle is made.
Property holding a SG store/key/clid/attr name from which a WriteDecorHandle is made.
Property holding a SG store/key/clid from which a WriteHandle is made.
MuonSegmentContainer_v1 MuonSegmentContainer
Definition of the current "MuonSegment container version".
Job-summed grouping-purity diagnostics: does a formed (kept) component mix segments from more than on...
std::array< std::atomic< std::size_t >, 3 *kSizeBins > sizeByOutcome
retained segments
std::array< std::atomic< std::size_t >, 3 > componentsByOutcome
clean / mixed / bkgOnly
std::array< std::atomic< std::size_t >, kColumns *3 > muonOutcome
clean/mixed/fragmented, per column
std::array< std::atomic< std::size_t >, 3 *kScoreBins > scoreByOutcome
Kept components split by outcome (clean / mixed / bkgOnly), index = outcome * nBins + bin.
std::array< std::atomic< std::size_t >, 3 *kLayerBins > layersByOutcome
distinct LayerIndex
std::array< std::atomic< std::size_t >, kSizeBins > componentSizeHist
static constexpr std::size_t kCrossScoreBins
Components spanning >= 2 layers (the only ones that can seed), per outcome:
std::array< std::atomic< std::size_t >, 3 *kCrossEdgeBins > crossEdgesByOutcome
number of cross-layer edges
std::array< std::atomic< std::size_t >, 3 *kCrossScoreBins > crossScoreByOutcome
strongest cross-layer edge
Job-summed classification of lost truth segments (classifyLostTruthSegments()).
std::array< std::atomic< std::size_t >, 4 > layerPair
IM / MO / IO / other (C).
std::array< std::atomic< std::size_t >, kCategories *kColumns > category
std::array< std::atomic< std::size_t >, 3 > precisionHits
nPrecisionHits <=4 / 5-6 / >=7 (C)
std::array< std::atomic< std::size_t >, 4 > muonsSeedable
truth muons with >= 2 input chambers (all / regions)
std::array< std::atomic< std::size_t >, 2 > sectorDelta
same / adjacent sector (C)
std::array< std::atomic< std::size_t >, 5 > scoreBin
best true-pair score of category C
std::array< std::atomic< std::size_t >, 4 > muonsSeedLost
... of which < 2 chambers retained
std::array< std::atomic< std::size_t >, 4 > muonSegments
muon has 2 / 3 / 4 / 5+ input segments (C)