ATLAS Offline Software
Loading...
Searching...
No Matches
MuonFastRecoTester.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
11
12namespace MuonValR4 {
13 using namespace MuonR4;
14 using namespace MuonVal;
16 using simHitSet = std::unordered_set<const xAOD::MuonSimHit*>;
17 using TruthParticleMap = std::map<const xAOD::TruthParticle*, std::vector<simHitSet>>;
18 std::optional<std::size_t> isTruthMatched (const SpacePoint* sp,
19 const TruthParticleMap& truthHits) {
20 for (const xAOD::MuonSimHit* hit : getMatchingSimHits(std::vector<const SpacePoint*>{sp})) {
21 std::size_t idx{0};
22 for (const auto& [tp, truthHitSets] : truthHits) {
23 for (const simHitSet& truthHitSet : truthHitSets) {
24 if (truthHitSet.count(hit)) {
25 if (tp) return idx;
26 else return truthHits.size(); // Pileup muon
27 }
28 }
29 if (tp) ++idx;
30 }
31 }
32 return std::nullopt;
33 };
34 bool isInPattern (const SpacePoint* sp,
35 const StIndex station,
36 const GlobalPattern& pattern){
37 for (const SpacePoint* hit : pattern.hitsInStation(station)) {
38 if (hit == sp) return true;
39 }
40 return false;
41 };
42
44 ATH_CHECK(m_geoCtxKey.initialize());
45 {
46 int infoOpts = 0;
47 if (m_isMC) infoOpts = EventInfoBranch::isMC;
48 m_tree.addBranch(std::make_unique<EventInfoBranch>(m_tree, infoOpts));
49 }
50 ATH_CHECK(m_spKey.initialize(!m_spKey.empty()));
51 ATH_CHECK(m_NSWspKey.initialize(!m_NSWspKey.empty()));
53 if (!m_spKey.empty()) {
54 m_spTester = std::make_shared<SpacePointTesterModule>(m_tree, m_spKey.key(), msgLevel(), "Muon");
55 m_tree.addBranch(m_spTester);
56 if (!m_isMC) m_tree.disableBranch(m_spMatchedToTruth.name());
57 }
58 if (!m_NSWspKey.empty()) {
59 m_NSWspTester = std::make_shared<SpacePointTesterModule>(m_tree, m_NSWspKey.key(), msgLevel(), "Nsw");
60 m_tree.addBranch(m_NSWspTester);
61 if (!m_isMC) m_tree.disableBranch(m_NSWspMatchedToTruth.name());
62 }
63 } else {
64 m_tree.disableBranch(m_spType.name());
65 m_tree.disableBranch(m_NSWspType.name());
66 m_tree.disableBranch(m_spMatchedToPattern.name());
67 m_tree.disableBranch(m_NSWspMatchedToPattern.name());
68 m_tree.disableBranch(m_spMatchedToTruth.name());
69 m_tree.disableBranch(m_NSWspMatchedToTruth.name());
70 }
71 if (!m_isMC) {
72 m_tree.disableBranch(m_gen_Eta.name());
73 m_tree.disableBranch(m_gen_Phi.name());
74 m_tree.disableBranch(m_gen_Pt.name());
75 m_tree.disableBranch(m_gen_Q.name());
76 m_tree.disableBranch(m_pat_nTrueNonPrecSpacePoints.name());
77 m_tree.disableBranch(m_pat_nTruePrecSpacePoints.name());
78 m_tree.disableBranch(m_pat_nTruePhiSpacePoints.name());
79 m_tree.disableBranch(m_pat_MatchedToTruth.name());
80 m_tree.disableBranch(m_pat_nTruthparticles.name());
81 }
82 ATH_CHECK(m_patternKey.initialize());
83 ATH_CHECK(m_truthSegmentKey.initialize(!m_truthSegmentKey.empty()));
84 ATH_CHECK(m_tree.init(this));
85 ATH_CHECK(m_idHelperSvc.retrieve());
86 return StatusCode::SUCCESS;
87 }
88
90 ATH_CHECK(m_tree.write());
91 return StatusCode::SUCCESS;
92 }
94
95 const EventContext& ctx = Gaudi::Hive::currentContext();
96 //const ActsTrk::GeometryContext* gctxPtr{nullptr};
97 //ATH_CHECK(SG::get(gctxPtr, m_geoCtxKey, ctx));
98
99 const SpacePointContainer* spContainer {nullptr};
100 ATH_CHECK(SG::get(spContainer, m_spKey, ctx));
101
102 const SpacePointContainer* NSWspContainer {nullptr};
103 ATH_CHECK(SG::get(NSWspContainer, m_NSWspKey, ctx));
104
105 const GlobalPatternContainer* globPatterns{nullptr};
106 ATH_CHECK(SG::get(globPatterns, m_patternKey, ctx));
107
108 const xAOD::MuonSegmentContainer* readTruthSegments{nullptr};
109 if(m_isMC){
110 ATH_CHECK(SG::get(readTruthSegments , m_truthSegmentKey, ctx));
111 }
112
113 ATH_MSG_DEBUG("Succesfully retrieved input collections. Global Patterns: "<<globPatterns->size()
114 <<", truth segments: "<<(readTruthSegments? readTruthSegments->size() : -1)<<".");
115
116 const TruthParticleMap truthMap{fillTruthMap(readTruthSegments)};
117 fillTruthInfo(truthMap, readTruthSegments);
118
119 if (m_writeSpacePoints) {
120 fillSpacePointInfo(spContainer, globPatterns, truthMap,
122 fillSpacePointInfo(NSWspContainer, globPatterns, truthMap,
124 }
125 fillGlobPatternInfo(globPatterns, truthMap,
126 std::vector<const MuonR4::SpacePointContainer*>{spContainer, NSWspContainer});
127
128 ATH_CHECK(m_tree.fill(ctx));
129 return StatusCode::SUCCESS;
130 }
132 if (!truthSegments) return TruthParticleMap{};
133
134 TruthParticleMap truthMap{};
135 for (const xAOD::MuonSegment* truth : *truthSegments) {
136 if (!truth) continue;
138 truthMap[tp].push_back(getMatchingSimHits(*truth));
139 }
140 return truthMap;
141 }
143 const xAOD::MuonSegmentContainer* truthSegments) {
144 using enum eHitType;
145 if (!m_isMC || truthHits.empty()) return;
146 int tpIdx{-1};
147 for (const auto& [tp, _] : truthHits) {
148 // We skip pileup muons
149 if(!tp) continue;
150
151 m_gen_Eta.push_back(tp->eta());
152 m_gen_Phi.push_back(tp->phi());
153 m_gen_Pt.push_back(tp->pt());
154 m_gen_Q.push_back(tp->charge());
155
156 ++tpIdx;
157 m_gen_nNonPrecSpacePointsPerStation[tpIdx].resize(Acts::toUnderlying(StIndex::StIndexMax));
158 m_gen_nPrecSpacePointsPerStation[tpIdx].resize(Acts::toUnderlying(StIndex::StIndexMax));
159 m_gen_nPhiSpacePointsPerStation[tpIdx].resize(Acts::toUnderlying(StIndex::StIndexMax));
160
161 for (const auto& segment : *truthSegments) {
162 if (!segment) continue;
163 if (getTruthMatchedParticle(*segment) != tp) continue;
164 const auto StIdx {Acts::toUnderlying(toStationIndex(segment->chamberIndex()))};
165 m_gen_nNonPrecSpacePointsPerStation[tpIdx][StIdx] += segment->nTrigEtaLayers();
166 m_gen_nPrecSpacePointsPerStation[tpIdx][StIdx] += segment->nPrecisionHits();
167 m_gen_nPhiSpacePointsPerStation[tpIdx][StIdx] += segment->nPhiLayers();
168 }
169 }
170 }
172 const MuonR4::GlobalPatternContainer* patternCont,
173 const TruthParticleMap& truthHits,
174 SpacePointTesterModule& spTester,
176 MuonVal::MatrixBranch<unsigned char>& spMatchedToPatternBranch,
177 MuonVal::MatrixBranch<unsigned char>& spMatchedToTruthBranch) const {
178 if (!spc) return;
179 for (const SpacePointBucket* bucket : *spc) {
180 for (const auto& sp : *bucket) {
181 spTypeBranch.push_back(MuonR4::isPrecisionHit(*sp) ? 2 : (sp->measuresEta() ? 1 : 3));
182 if(!m_isMC) continue;
183 if (const auto tpIdx {isTruthMatched(sp.get(), truthHits)}; tpIdx.has_value()) {
184 unsigned treeIdx = spTester.push_back(*sp);
185 spMatchedToTruthBranch[tpIdx.value()].push_back(treeIdx);
186 }
187 }
188 }
189 std::size_t patternIdx{0};
190 for (const GlobalPattern* pattern : *patternCont) {
191 for (const StIndex station : pattern->getStations()) {
192 for (const SpacePoint* sp : pattern->hitsInStation(station)) {
193 unsigned treeIdx = spTester.push_back(*sp);
194 spMatchedToPatternBranch[patternIdx].push_back(treeIdx);
195 }
196 }
197 ++patternIdx;
198 }
199 }
201 const TruthParticleMap& truthHits,
202 const std::vector<const MuonR4::SpacePointContainer*>& spContainers) {
203 using enum eHitType;
204 auto updateCounts = [](HitCounts& hitCount, const SpacePoint* sp){
205 const bool isPrec = MuonR4::isPrecisionHit(*sp);
206 const bool isTriggerEta = !isPrec && sp->measuresEta();
207 hitCount[Acts::toUnderlying(ePrec)] += isPrec;
208 hitCount[Acts::toUnderlying(eTriggerEta)] += isTriggerEta;
209 hitCount[Acts::toUnderlying(ePhi)] += sp->measuresPhi();
210 };
211 m_pat_n = patternCont->size();
212 std::size_t patternIdx{0};
213 for (const GlobalPattern* pattern : *patternCont) {
214 PatternHitCount patHitCount{};
215 const std::vector<StIndex> stations {pattern->getStations()};
216 for (const StIndex station : stations) {
217 for (const SpacePoint* sp : pattern->hitsInStation(station)) {
218 updateCounts(patHitCount.hitCounts, sp);
219
220 if (!m_isMC) continue;
221 if (const auto tpIdx {isTruthMatched(sp, truthHits)}; tpIdx.has_value()) {
222 updateCounts(tpIdx.value() < truthHits.size() ? patHitCount.trueHitCounts : patHitCount.pileupHitCounts, sp);
223 auto& matchedTPs = m_pat_MatchedToTruth[patternIdx];
224 if (std::ranges::find(matchedTPs, tpIdx.value()) == matchedTPs.end()) {
225 matchedTPs.push_back(tpIdx.value());
226 }
227 }
228 }
229 }
230 for (const SpacePointContainer* spContainer : spContainers) {
231 if (!spContainer) continue;
232 for (const SpacePointBucket* bucket : *spContainer) {
233 bool bucketInPattern{false};
234 const StIndex bucketStation {m_idHelperSvc->stationIndex(bucket->front()->identify())};
235 std::vector<const SpacePoint*> allHits{};
236
237 for (const auto& sp : *bucket) {
238 if (isInPattern(sp.get(), bucketStation, *pattern)) {
239 bucketInPattern = true;
240 }
241 allHits.push_back(sp.get());
242 }
243 if (bucketInPattern) {
244 for (const SpacePoint* sp : allHits) {
245 updateCounts(patHitCount.allHitCounts, sp);
246 }
247 }
248 }
249 }
250 m_pat_nNonPrecSpacePoints.push_back(patHitCount.hitCounts[Acts::toUnderlying(eTriggerEta)]);
251 m_pat_nPrecSpacePoints.push_back(patHitCount.hitCounts[Acts::toUnderlying(ePrec)]);
252 m_pat_nPhiSpacePoints.push_back(patHitCount.hitCounts[Acts::toUnderlying(ePhi)]);
253
254 m_pat_nAllNonPrecSpacePoints.push_back(patHitCount.allHitCounts[Acts::toUnderlying(eTriggerEta)]);
255 m_pat_nAllPrecSpacePoints.push_back(patHitCount.allHitCounts[Acts::toUnderlying(ePrec)]);
256 m_pat_nAllPhiSpacePoints.push_back(patHitCount.allHitCounts[Acts::toUnderlying(ePhi)]);
257
258 m_pat_Eta.push_back(-std::log(std::tan(pattern->theta()/2.)));
259 m_pat_phi.push_back(pattern->phi());
260 m_pat_sector1.push_back(pattern->sector());
261 m_pat_sector2.push_back(pattern->secondarySector());
262 m_pat_residual.push_back(pattern->totalResidual());
263 m_pat_normalizedResidual.push_back(pattern->totalNormalizedResidual());
264 m_pat_side.push_back(pattern->hitsInStation(stations.front()).front()->msSector()->side());
265 m_pat_nStations.push_back(stations.size());
266
267 if(m_isMC) {
269 m_pat_nTrueNonPrecSpacePoints.push_back(patHitCount.trueHitCounts[Acts::toUnderlying(eTriggerEta)]);
270 m_pat_nTruePrecSpacePoints.push_back(patHitCount.trueHitCounts[Acts::toUnderlying(ePrec)]);
271 m_pat_nTruePhiSpacePoints.push_back(patHitCount.trueHitCounts[Acts::toUnderlying(ePhi)]);
272
273 m_pat_nPileupNonPrecSpacePoints.push_back(patHitCount.pileupHitCounts[Acts::toUnderlying(eTriggerEta)]);
274 m_pat_nPileupPrecSpacePoints.push_back(patHitCount.pileupHitCounts[Acts::toUnderlying(ePrec)]);
275 m_pat_nPileupPhiSpacePoints.push_back(patHitCount.pileupHitCounts[Acts::toUnderlying(ePhi)]);
276
277 m_pat_nTruthparticles.push_back(std::ranges::count_if(m_pat_MatchedToTruth[patternIdx],
278 [&truthHits](unsigned char tpIdx){ return tpIdx < truthHits.size(); }));
279 }
280 patternIdx++;
281 }
282
283 }
284} // namespace MuonValR4
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x)
static Double_t sp
size_type size() const noexcept
Returns the number of elements in the collection.
Data class to represent an eta maximum in hough space.
: The muon space point bucket represents a collection of points that will bre processed together in t...
The muon space point is the combination of two uncalibrated measurements one of them measures the eta...
MuonVal::VectorBranch< float > & m_gen_Phi
MuonVal::VectorBranch< unsigned char > & m_spType
Type of spacepoints: 1 for trigger eta, 2 for precision, 3 for only-phi.
SG::ReadHandleKey< MuonR4::SpacePointContainer > m_NSWspKey
SG::ReadHandleKey< MuonR4::GlobalPatternContainer > m_patternKey
MuonVal::ScalarBranch< unsigned > & m_pat_n
====== Global Pattern block ===========
void fillTruthInfo(const TruthParticleMap &truthHits, const xAOD::MuonSegmentContainer *truthSegments)
Fill the truth particleinformation into the tree.
MuonVal::MatrixBranch< unsigned char > & m_spMatchedToPattern
Branch indicating which space points in the tree are associated to the i-th pattern.
MuonVal::VectorBranch< unsigned char > & m_pat_nPileupNonPrecSpacePoints
Number of pileup trigger eta space points in the pattern.
MuonVal::VectorBranch< unsigned char > & m_pat_nAllPrecSpacePoints
Number of precision space points in the buckets crossed by the pattern.
MuonVal::VectorBranch< unsigned char > & m_pat_nStations
Number of stations.
MuonVal::MatrixBranch< unsigned char > & m_NSWspMatchedToTruth
MuonVal::VectorBranch< uint16_t > & m_pat_sector2
MuonVal::VectorBranch< float > & m_gen_Eta
MuonVal::VectorBranch< unsigned char > & m_pat_nAllPhiSpacePoints
Number of phi space points in the buckets crossed by the pattern.
MuonVal::VectorBranch< unsigned char > & m_pat_nPhiSpacePoints
Number of phi measurements in the pattern.
Gaudi::Property< bool > m_writeSpacePoints
MuonVal::VectorBranch< float > & m_pat_phi
MuonVal::VectorBranch< float > & m_pat_normalizedResidual
pattern normalized residual
MuonVal::VectorBranch< unsigned char > & m_pat_nTrueNonPrecSpacePoints
Number of truth trigger eta space points in the pattern.
MuonVal::VectorBranch< unsigned char > & m_pat_nPileupPhiSpacePoints
Number of pileup phi space points in the pattern.
virtual StatusCode execute() override
std::map< const xAOD::TruthParticle *, std::vector< simHitSet > > TruthParticleMap
MuonVal::VectorBranch< unsigned char > & m_pat_nTruePrecSpacePoints
Number of truth precision space points in the pattern.
MuonVal::VectorBranch< short > & m_gen_Q
====== Truth particle block ===========
SG::ReadHandleKey< ActsTrk::GeometryContext > m_geoCtxKey
MuonVal::MatrixBranch< unsigned char > & m_gen_nNonPrecSpacePointsPerStation
Number of trigger eta measurements per station.
virtual StatusCode finalize() override
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
MuonVal::VectorBranch< unsigned char > & m_pat_nPileupPrecSpacePoints
Number of pileup precision space points in the pattern.
MuonVal::MatrixBranch< unsigned char > & m_gen_nPhiSpacePointsPerStation
Number of phi measurements per station.
SG::ReadHandleKey< xAOD::MuonSegmentContainer > m_truthSegmentKey
std::shared_ptr< SpacePointTesterModule > m_NSWspTester
std::shared_ptr< SpacePointTesterModule > m_spTester
====== Spacepoint block ===========
virtual StatusCode initialize() override
MuonVal::VectorBranch< unsigned char > & m_pat_nNonPrecSpacePoints
Number of trigger eta space points in the pattern.
Gaudi::Property< bool > m_isMC
MuonVal::VectorBranch< unsigned char > & m_pat_nTruthparticles
number of matched truth particles
MuonVal::VectorBranch< float > & m_gen_Pt
void fillSpacePointInfo(const MuonR4::SpacePointContainer *spc, const MuonR4::GlobalPatternContainer *patternCont, const TruthParticleMap &truthHits, SpacePointTesterModule &spTester, MuonVal::VectorBranch< unsigned char > &spTypeBranch, MuonVal::MatrixBranch< unsigned char > &spMatchedToPatternBranch, MuonVal::MatrixBranch< unsigned char > &spMatchedToTruthBranch) const
Fill the space point information into the tree.
MuonVal::VectorBranch< unsigned char > & m_NSWspType
void fillGlobPatternInfo(const MuonR4::GlobalPatternContainer *patternCont, const TruthParticleMap &truthHits, const std::vector< const MuonR4::SpacePointContainer * > &spContainers)
Fill the info associated to the global patterns into the tree.
MuonVal::VectorBranch< uint16_t > & m_pat_sector1
pattern primary & secondary sectors (different if the pattern is in the sector overlap)
MuonVal::MatrixBranch< unsigned char > & m_NSWspMatchedToPattern
MuonVal::VectorBranch< float > & m_pat_residual
pattern residual
MuonVal::MuonTesterTree m_tree
MuonVal::VectorBranch< unsigned char > & m_pat_nAllNonPrecSpacePoints
Number of trigger eta space points in the buckets crossed by the pattern.
MuonVal::VectorBranch< short > & m_pat_side
+1 for A-, -1 of C-side
MuonVal::MatrixBranch< unsigned char > & m_pat_MatchedToTruth
Branch indicating which truth particles in the tree are associated to the i-th pattern.
MuonVal::VectorBranch< unsigned char > & m_pat_nPrecSpacePoints
Number of precision measurements in the pattern.
MuonVal::MatrixBranch< unsigned char > & m_gen_nPrecSpacePointsPerStation
Number of precision measurements per station.
TruthParticleMap fillTruthMap(const xAOD::MuonSegmentContainer *truthSegments) const
Fill the truth particle map.
std::array< unsigned int, Acts::toUnderlying(eHitType::nTypes)> HitCounts
MuonVal::MatrixBranch< unsigned char > & m_spMatchedToTruth
Branch indicating which space points in the tree are associated to the i-th truth particle.
MuonVal::VectorBranch< float > & m_pat_Eta
pattern average theta & phi
MuonVal::VectorBranch< unsigned char > & m_pat_nTruePhiSpacePoints
Number of truth phi space points in the pattern.
SG::ReadHandleKey< MuonR4::SpacePointContainer > m_spKey
unsigned int push_back(const MuonR4::SpacePointBucket &bucket)
@ isMC
Flag determining whether the branch is simulation.
void push_back(size_t i, const T &value)
void push_back(const T &value)
Adds a new element at the end of the vector.
const xAOD::TruthParticle * getTruthMatchedParticle(const xAOD::MuonSegment &segment)
Returns the particle truth-matched to the segment.
std::unordered_set< const xAOD::MuonSimHit * > getMatchingSimHits(const xAOD::MuonSegment &segment)
: Returns all sim hits matched to a xAOD::MuonSegment
DataVector< GlobalPattern > GlobalPatternContainer
Abrivation of the GlobalPattern container type.
bool isPrecisionHit(const SpacePoint &hit)
Returns whether the uncalibrated spacepoint is a precision hit (Mdt, micromegas, stgc strips)
DataVector< SpacePointBucket > SpacePointContainer
Abrivation of the space point container type.
Lightweight algorithm to read xAOD MDT sim hits and (fast-digitised) drift circles from SG and fill a...
std::optional< std::size_t > isTruthMatched(const SpacePoint *sp, const TruthParticleMap &truthHits)
bool isInPattern(const SpacePoint *sp, const StIndex station, const GlobalPattern &pattern)
std::map< const xAOD::TruthParticle *, std::vector< simHitSet > > TruthParticleMap
std::unordered_set< const xAOD::MuonSimHit * > simHitSet
StIndex
enum to classify the different station layers in the muon spectrometer
StIndex toStationIndex(ChIndex index)
convert ChIndex into StIndex
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
MuonSegmentContainer_v1 MuonSegmentContainer
Definition of the current "MuonSegment container version".
MuonSimHit_v1 MuonSimHit
Defined the version of the MuonSimHit.
Definition MuonSimHit.h:12
TruthParticle_v1 TruthParticle
Typedef to implementation.
MuonSegment_v1 MuonSegment
Reference the current persistent version: