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
12#include "CxxUtils/phihelper.h"
13
14namespace {
15 static const Muon::MuonSectorMapping sectorMap{};
16
17 void resize_all (const std::size_t nEle, const std::size_t size, auto&&... vecs) {
18 for (std::size_t idx = 0; idx < nEle; ++idx) {
19 (vecs[idx].resize(size), ...);
20 }
21 };
22}
23
24namespace MuonValR4 {
25 using namespace MuonR4;
26 using namespace MuonVal;
28 constexpr std::size_t s_nStations {Acts::toUnderlying(StIndex::StIndexMax)};
29 using simHitSet = std::unordered_set<const xAOD::MuonSimHit*>;
30 using TruthParticleMap = std::map<const xAOD::TruthParticle*, std::vector<simHitSet>>;
31 std::optional<std::size_t> isTruthMatched (const xAOD::MuonMeasurement& meas,
32 const TruthParticleMap& truthHits) {
33 const xAOD::MuonSimHit* hit {getTruthMatchedHit(meas)};
34 if (!hit) return std::nullopt;
35 std::size_t idx{0};
36 for (const auto& [tp, truthHitSets] : truthHits) {
37 for (const simHitSet& truthHitSet : truthHitSets) {
38 if (truthHitSet.count(hit)) {
39 if (tp) return idx;
40 else return truthHits.size(); // Pileup muon
41 }
42 }
43 if (tp) ++idx;
44 }
45 return std::nullopt;
46 };
47 bool isInPattern (const SpacePoint* sp,
48 const StIndex station,
49 const GlobalPattern& pattern){
50 for (const SpacePoint* hit : pattern.hitsInStation(station)) {
51 if (hit == sp) return true;
52 }
53 return false;
54 };
55
57 ATH_CHECK(m_geoCtxKey.initialize());
58 {
59 int infoOpts = 0;
60 if (m_isMC) infoOpts = EventInfoBranch::isMC;
61 m_tree.addBranch(std::make_unique<EventInfoBranch>(m_tree, infoOpts));
62 }
63 ATH_CHECK(m_spKey.initialize(!m_spKey.empty()));
64 ATH_CHECK(m_NSWspKey.initialize(!m_NSWspKey.empty()));
67 if (!m_spKey.empty()) {
68 m_spTester = std::make_shared<SpacePointTesterModule>(m_tree, m_spKey.key(), msgLevel(), "Muon");
69 m_tree.addBranch(m_spTester);
70 if (!m_isMC) m_tree.disableBranch(m_spMatchedToTruth.name());
71 }
72 if (!m_NSWspKey.empty()) {
73 m_NSWspTester = std::make_shared<SpacePointTesterModule>(m_tree, m_NSWspKey.key(), msgLevel(), "Nsw");
74 m_tree.addBranch(m_NSWspTester);
75 if (!m_isMC) m_tree.disableBranch(m_NSWspMatchedToTruth.name());
76 }
77 } else {
78 m_tree.disableBranch(m_spType.name());
79 m_tree.disableBranch(m_NSWspType.name());
80 m_tree.disableBranch(m_spMatchedToPattern.name());
81 m_tree.disableBranch(m_NSWspMatchedToPattern.name());
82 m_tree.disableBranch(m_spMatchedToTruth.name());
83 m_tree.disableBranch(m_NSWspMatchedToTruth.name());
84 }
85 if (!m_isMC) {
86 m_tree.disableBranch(m_gen_Eta.name());
87 m_tree.disableBranch(m_gen_Phi.name());
88 m_tree.disableBranch(m_gen_Pt.name());
89 m_tree.disableBranch(m_gen_Q.name());
90 m_tree.disableBranch(m_pat_nTruthNonPrecMeas.name());
91 m_tree.disableBranch(m_pat_nTruthPrecMeas.name());
92 m_tree.disableBranch(m_pat_nTruthPhiMeas.name());
93 m_tree.disableBranch(m_pat_MatchedToTruth.name());
94 }
95 if (!m_isSeededReco) {
96 m_tree.disableBranch(m_roi_EtaMin.name());
97 m_tree.disableBranch(m_roi_EtaMax.name());
98 m_tree.disableBranch(m_roi_PhiMin.name());
99 m_tree.disableBranch(m_roi_PhiMax.name());
100 m_tree.disableBranch(m_roi_ZMin.name());
101 m_tree.disableBranch(m_roi_ZMax.name());
102 }
103 ATH_CHECK(m_patternKey.initialize());
104 ATH_CHECK(m_truthSegmentKey.initialize(!m_truthSegmentKey.empty()));
105 ATH_CHECK(m_tree.init(this));
106 ATH_CHECK(m_idHelperSvc.retrieve());
107 return StatusCode::SUCCESS;
108 }
109
111 ATH_CHECK(m_tree.write());
112 return StatusCode::SUCCESS;
113 }
115
116 const EventContext& ctx = Gaudi::Hive::currentContext();
117 //const ActsTrk::GeometryContext* gctxPtr{nullptr};
118 //ATH_CHECK(SG::get(gctxPtr, m_geoCtxKey, ctx));
119
120 const SpacePointContainer* spContainer {nullptr};
121 ATH_CHECK(SG::get(spContainer, m_spKey, ctx));
122
123 const SpacePointContainer* NSWspContainer {nullptr};
124 ATH_CHECK(SG::get(NSWspContainer, m_NSWspKey, ctx));
125
126 const GlobalPatternContainer* globPatterns{nullptr};
127 ATH_CHECK(SG::get(globPatterns, m_patternKey, ctx));
128
129 const xAOD::MuonSegmentContainer* readTruthSegments{nullptr};
130 if(m_isMC){
131 ATH_CHECK(SG::get(readTruthSegments , m_truthSegmentKey, ctx));
132 }
133 const TrigRoiDescriptorCollection* roiCollection{nullptr};
134 if(m_isSeededReco) {
135 ATH_CHECK(SG::get(roiCollection, m_roiCollectionKey, ctx));
136 }
137
138 ATH_MSG_DEBUG("Succesfully retrieved input collections: Global Patterns: "<<globPatterns->size()
139 <<", truth segments: "<<(readTruthSegments? readTruthSegments->size() : -1)
140 <<", Rois: "<<(roiCollection ? roiCollection->size() : -1));
141
142 const TruthParticleMap truthMap{fillTruthMap(readTruthSegments, roiCollection)};
143 fillTruthInfo(truthMap, {spContainer, NSWspContainer});
144 fillRoIInfo(roiCollection);
145
146 if (m_writeSpacePoints) {
147 fillSpacePointInfo(spContainer, globPatterns, truthMap,
149 fillSpacePointInfo(NSWspContainer, globPatterns, truthMap,
151 }
152 fillGlobPatternInfo(globPatterns, truthMap,
153 std::vector<const MuonR4::SpacePointContainer*>{spContainer, NSWspContainer});
154
155 ATH_CHECK(m_tree.fill(ctx));
156 return StatusCode::SUCCESS;
157 }
159 const TrigRoiDescriptorCollection* roiCollection) const {
160 if (!truthSegments) return TruthParticleMap{};
161 ATH_MSG_VERBOSE("Filling truth map with "<<truthSegments->size());
163 auto isInROI = [roiCollection](const xAOD::TruthParticle* tp) {
164 for (const TrigRoiDescriptor* roi : *roiCollection) {
166 if (tp->eta() < roi->etaMinus() || tp->eta() > roi->etaPlus()) continue;
168 const double dPhiPlus = CxxUtils::deltaPhi(roi->phiPlus(), tp->phi());
169 const double dPhiMinus = CxxUtils::deltaPhi(roi->phiMinus(), tp->phi());
170 if (dPhiPlus >= 0. && dPhiMinus <= 0.) return true;
171 }
172 return false;
173 };
174
175 TruthParticleMap truthMap{};
176 for (const xAOD::MuonSegment* truth : *truthSegments) {
178 // In case of seeded reco, we only save truth particles that are in the RoIs
179 if (!m_isSeededReco || !tp || isInROI(tp)){
180 truthMap[tp].push_back(getMatchingSimHits(*truth));
181 }
182 }
183 return truthMap;
184 }
186 const std::vector<const MuonR4::SpacePointContainer*>& spContainers) {
187 if (!m_isMC || truthHits.empty()) return;
188 resize_all(truthHits.size(), s_nStations,
190 using enum measType;
191 using LayerBookeeper = std::unordered_map<const MuonGMR4::SpectrometerSector*, std::set<unsigned>>;
192 using MeasBookeeper = std::array<std::vector<const SpacePoint*>, Acts::toUnderlying(nTypes)>;
194 MeasBookeeper measInStation{};
195 LayerBookeeper seenEtaLayers{};
196 LayerBookeeper seenPhiLayers{};
197
198 auto processMeas = [&truthHits, &measInStation, &seenEtaLayers, &seenPhiLayers, this]
199 (const SpacePoint* sp, const measType type, const bool process2Dmeas, const int tpIdx, const std::size_t stIdx) {
201 const bool isPrec {MuonR4::isPrecisionHit(*sp)};
202 if ((type == Prec && !isPrec) ||
203 (type == NonPrec && (isPrec || !sp->measuresEta())) || (type == Phi && sp->measuresEta())) {
204 return;
205 }
206 /* Check if the hit has already been counted, i.e. duplicated hits. Needed for precision hits, since we can have multiple on the same layer */
207 std::vector<const SpacePoint*>& outCont {measInStation[Acts::toUnderlying(type)]};
208 if (std::ranges::find_if(outCont, [sp](const SpacePoint* s) {
209 return s->primaryMeasurement() == sp->primaryMeasurement(); }) != outCont.end()) {
210 return;
211 }
213 if (isTruthMatched(*sp->primaryMeasurement(), truthHits) != tpIdx) return;
214
215 const bool isDoubleMatched {sp->dimension() == 2u && sp->secondaryMeasurement() && isTruthMatched(*sp->secondaryMeasurement(), truthHits) == tpIdx};
216 if (process2Dmeas && !isDoubleMatched) return;
217
218 /* Check if we have already measurements in the same layer, except for precision hits */
219 const unsigned layNum {m_spSorter.sectorLayerNum(*sp)};
220 ATH_MSG_VERBOSE("---> "<<(isPrec ? "Prec" : (type == NonPrec ? "Trig" : "Phi "))<< " " << *sp << " in sector "<<sp->msSector()->identString() << " lay "<<layNum);
221 if (sp->measuresEta()) {
222 const bool isSeenLayer {seenEtaLayers[sp->msSector()].count(layNum) > 0};
223 if (isSeenLayer && !sp->isStraw()) return;
224 if (!isSeenLayer) seenEtaLayers[sp->msSector()].insert(layNum);
225
226 auto& measCounter = isPrec ? m_gen_nPrecMeas : m_gen_nNonPrecMeas;
227 ++measCounter[tpIdx][stIdx];
228
229 // Eta hit can also have phi measurements. For combined spacepoints, need to be check the secondaty measurements. No need for 2D spacepoints.
230 if (sp->measuresPhi() && isDoubleMatched) {
231 seenPhiLayers[sp->msSector()].insert(layNum);
232 ++m_gen_nPhiMeas[tpIdx][stIdx];
233 measInStation[Acts::toUnderlying(Phi)].push_back(sp);
234 }
235 } else {
236 if (seenPhiLayers[sp->msSector()].count(layNum) > 0) return;
237 seenPhiLayers[sp->msSector()].insert(layNum);
238 ++m_gen_nPhiMeas[tpIdx][stIdx];
239 }
240 outCont.push_back(sp);
241 };
242
243 int tpIdx{-1};
244 for (const auto& [tp, _] : truthHits) {
245 if(!tp) continue;
246 m_gen_Eta.push_back(tp->eta());
247 m_gen_Phi.push_back(tp->phi());
248 m_gen_Pt.push_back(tp->pt());
249 m_gen_Q.push_back(tp->charge());
250 ++tpIdx;
251 // Save the sectors compatible for the tp
252 std::vector<int> sectors{};
253 sectorMap.getSectors(tp->phi(), sectors);
254 const int side {tp->eta() > 0 ? 1 : -1};
257 ATH_MSG_VERBOSE("tp: " << tpIdx << ", Eta: " << tp->eta() << ", Phi: " << tp->phi() << ", Pt [GeV]: " << tp->pt() * 1e-3 << ", Q: " << tp->charge());
258 for (std::size_t stIdx = 0; stIdx < s_nStations; ++stIdx) {
259 ATH_MSG_VERBOSE("\tStation "<< stName(static_cast<StIndex>(stIdx)) << ": matched hits before layer deduplication: ");
260 // Clear the bookkeeping structures for the new station
261 for (auto& vec : measInStation) vec.clear();
262 seenEtaLayers.clear();
263 seenPhiLayers.clear();
264 // We fill per measurement type, so we give priority to precision hits if they are in the same layer as trigger hits, e.g. sTGCs
265 for (const measType type : {Prec, NonPrec, Phi}) {
266 // We fill first 2D measurements and then 1D ones
267 for (const bool process2Dmeas : {true, false}) {
268 for (const auto& spContainer : spContainers) {
269 if (!spContainer) continue;
270 for (const SpacePointBucket* bucket : *spContainer) {
272 if (static_cast<std::size_t>(m_idHelperSvc->stationIndex(bucket->front()->identify())) != stIdx) continue;
274 if (bucket->msSector()->side() != side ||
275 std::ranges::none_of(sectors, [&](int s){ return bucket->msSector()->sector() == s; })) {
276 continue;
277 }
278 for (const auto& sp : *bucket) {
279 /* Process first the precision hits, 2D measurements first and then 1D */
280 processMeas(sp.get(), type, process2Dmeas, tpIdx, stIdx);
281 }
282 } // End loop over buckets
283 } // End loop over containers
284 } // End loop over "process2Dmeas" flag
285 } // End loop over measurement types
286 ATH_MSG_VERBOSE("\t after deduplication: N trig/Prec/phi meas: "
287 << static_cast<std::size_t>(m_gen_nNonPrecMeas[tpIdx][stIdx]) << "/"
288 << static_cast<std::size_t>(m_gen_nPrecMeas[tpIdx][stIdx]) << "/"
289 << static_cast<std::size_t>(m_gen_nPhiMeas[tpIdx][stIdx]));
290 } // End loop over stations
291 } // End loop over truth particles
292 }
294 if (!m_isSeededReco || !roiCollection || roiCollection->empty()) return;
295 for (const TrigRoiDescriptor* roi : *roiCollection) {
296 m_roi_EtaMin.push_back(roi->etaMinus());
297 m_roi_EtaMax.push_back(roi->etaPlus());
298 m_roi_PhiMin.push_back(roi->phiMinus());
299 m_roi_PhiMax.push_back(roi->phiPlus());
300 m_roi_ZMin.push_back(roi->zedMinus());
301 m_roi_ZMax.push_back(roi->zedPlus());
302 }
303 }
305 const MuonR4::GlobalPatternContainer* patternCont,
306 const TruthParticleMap& truthHits,
307 SpacePointTesterModule& spTester,
309 MuonVal::MatrixBranch<unsigned char>& spMatchedToPatternBranch,
310 MuonVal::MatrixBranch<unsigned char>& spMatchedToTruthBranch) const {
311 if (!spc) return;
312 for (const SpacePointBucket* bucket : *spc) {
313 for (const auto& sp : *bucket) {
315 spTypeBranch.push_back(Acts::toUnderlying(type));
316 if(!m_isMC) continue;
317 if (const auto tpIdx {isTruthMatched(*sp->primaryMeasurement(), truthHits)}; tpIdx.has_value()) {
318 unsigned treeIdx = spTester.push_back(*sp);
319 spMatchedToTruthBranch[tpIdx.value()].push_back(treeIdx);
320 }
321 }
322 }
323 std::size_t patternIdx{0};
324 for (const GlobalPattern* pattern : *patternCont) {
325 for (const StIndex station : pattern->getStations()) {
326 for (const SpacePoint* sp : pattern->hitsInStation(station)) {
327 unsigned treeIdx = spTester.push_back(*sp);
328 spMatchedToPatternBranch[patternIdx].push_back(treeIdx);
329 }
330 }
331 ++patternIdx;
332 }
333 }
335 const TruthParticleMap& truthHits,
336 const std::vector<const MuonR4::SpacePointContainer*>& spContainers) {
337 m_pat_n = patternCont->size();
338 // Resize all the matrix branches
339 resize_all(patternCont->size(), s_nStations,
343 if (m_isMC) {
344 resize_all(patternCont->size(), s_nStations,
347 }
348 auto isSecondaryMatched = [&truthHits](const SpacePoint* sp, std::size_t tpIdx) {
349 return sp->secondaryMeasurement() && isTruthMatched(*sp->secondaryMeasurement(), truthHits) == tpIdx;
350 };
351 std::size_t patternIdx{0};
352 for (const GlobalPattern* pattern : *patternCont) {
353 // We define a map of truth particles and associated hits for the current pattern, so we can determine the main truth particle is multiple are associated
354 std::unordered_map<std::size_t, std::vector<const SpacePoint*>> patternTruthHits{};
355
356 const std::vector<StIndex> stations {pattern->getStations()};
357 for (const StIndex station : stations) {
358 for (const SpacePoint* sp : pattern->hitsInStation(station)) {
359 updatePatHitInfo(ePatBranchType::eReco, patternIdx, station, sp);
360
361 if (!m_isMC) continue;
362 if (const auto tpIdx {isTruthMatched(*sp->primaryMeasurement(), truthHits)}; tpIdx.has_value()) {
363 // By convention, if truth particle index is equal to the size of the truth map, it means it's a pileup particle
364 if (*tpIdx >= truthHits.size() ) {
365 updatePatHitInfo(ePatBranchType::ePileup, patternIdx, station, sp, isSecondaryMatched(sp, *tpIdx));
366 } else {
367 patternTruthHits[*tpIdx].push_back(sp);
368 }
369 }
370 }
371 }
372 if (!patternTruthHits.empty()) {
373 // Sort the TPs by number of matched hits and define the main truth particle as the one with the most hits in the pattern
374 std::vector<std::size_t> sortedTPs {};
375 std::ranges::transform(patternTruthHits, std::back_inserter(sortedTPs), [](const auto& pair){ return pair.first; });
376 std::ranges::sort(sortedTPs, [&patternTruthHits](const auto& a, const auto& b){
377 return patternTruthHits.at(a).size() > patternTruthHits.at(b).size();
378 });
379 const auto mainTP = sortedTPs.front();
380 for (const SpacePoint* sp : patternTruthHits[mainTP]) {
381 const StIndex station {m_idHelperSvc->stationIndex(sp->identify())};
382 updatePatHitInfo(ePatBranchType::eTruth, patternIdx, station, sp, isSecondaryMatched(sp, mainTP));
383 }
384 // Add truth hits that are matched to other truth particles than the main one
385 for (const auto& [tpIdx, hits] : patternTruthHits) {
386 if (tpIdx == mainTP) continue;
387 for (const SpacePoint* sp : hits) {
388 const StIndex station {m_idHelperSvc->stationIndex(sp->identify())};
389 updatePatHitInfo(ePatBranchType::eMismatched, patternIdx, station, sp, isSecondaryMatched(sp, tpIdx));
390 }
391 }
392 // Save the matched truth particle index in the tree, either is a signal or pileup particle
393 std::ranges::transform(sortedTPs, std::back_inserter(m_pat_MatchedToTruth[patternIdx]), [](const auto& tp){ return tp; });
394 }
395 // Loop over the space point containers to count the number of hits in the buckets crossed by the pattern
396 for (const SpacePointContainer* spContainer : spContainers) {
397 if (!spContainer) continue;
398 for (const SpacePointBucket* bucket : *spContainer) {
399 bool bucketInPattern{false};
400 const StIndex bucketStation {m_idHelperSvc->stationIndex(bucket->front()->identify())};
401 std::vector<const SpacePoint*> allHits{};
402
403 for (const auto& sp : *bucket) {
404 if (isInPattern(sp.get(), bucketStation, *pattern)) {
405 bucketInPattern = true;
406 }
407 allHits.push_back(sp.get());
408 }
409 if (bucketInPattern) {
410 for (const SpacePoint* sp : allHits) {
411 updatePatHitInfo(ePatBranchType::eAll, patternIdx, bucketStation, sp);
412 }
413 }
414 }
415 }
416 m_pat_Eta.push_back(-std::log(std::tan(pattern->theta()/2.)));
417 m_pat_phi.push_back(pattern->phi());
418 m_pat_sector1.push_back(pattern->sector());
419 m_pat_sector2.push_back(pattern->secondarySector());
420 m_pat_meanNormResidual2.push_back(pattern->meanNormResidual2());
421 m_pat_side.push_back(pattern->hitsInStation(stations.front()).front()->msSector()->side());
422 m_pat_nStations.push_back(stations.size());
423
424 if (msgLevel(MSG::VERBOSE)) {
425 const auto mainTP {m_pat_MatchedToTruth[patternIdx].size() > 0 ? static_cast<int>(m_pat_MatchedToTruth[patternIdx].front()) : -1};
426 unsigned nPrecHits{0}, nNonPrecHits{0}, nPhiHits{0};
427 unsigned gen_nPrecHits{0}, gen_nNonPrecHits{0}, gen_nPhiHits{0};
428 for (std::size_t stIdx = 0; stIdx < s_nStations; ++stIdx) {
429 nPrecHits += static_cast<unsigned>(m_pat_nTruthPrecMeas[patternIdx][stIdx]);
430 nNonPrecHits += static_cast<unsigned>(m_pat_nTruthNonPrecMeas[patternIdx][stIdx]);
431 nPhiHits += static_cast<unsigned>(m_pat_nTruthPhiMeas[patternIdx][stIdx]);
432 if (mainTP < 0) continue;
433 gen_nPrecHits += static_cast<unsigned>(m_gen_nPrecMeas[mainTP][stIdx]);
434 gen_nNonPrecHits += static_cast<unsigned>(m_gen_nNonPrecMeas[mainTP][stIdx]);
435 gen_nPhiHits += static_cast<unsigned>(m_gen_nPhiMeas[mainTP][stIdx]);
436 }
437 ATH_MSG_VERBOSE("Pat #" << patternIdx<< ": " << *pattern << "mainTP: "<<std::to_string(mainTP)
438 <<", nTruthMatchedHits Trig: "<<nNonPrecHits<<" / "<<gen_nNonPrecHits<<", Prec: "<<nPrecHits<<" / "<<gen_nPrecHits<<", Phi: "<<nPhiHits<<" / "<<gen_nPhiHits);
439 }
440 patternIdx++;
441 }
442
443 }
444
446 const std::size_t patIdx,
448 const MuonR4::SpacePoint* sp,
449 const bool isSecondaryMatched) {
450 using enum ePatBranchType;
451 const bool isTruthInfo = (type == ePatBranchType::eTruth || type == ePatBranchType::eMismatched);
452 const auto updateCounts = [&](unsigned char& nonPrecCount,
453 unsigned char& precCount,
454 unsigned char& phiCount) {
455 if (sp->measuresEta()) {
456 if (MuonR4::isPrecisionHit(*sp)) precCount++;
457 else nonPrecCount++;
459 ATH_MSG_VERBOSE("---> "<<(MuonR4::isPrecisionHit(*sp) ? "Prec" : "Trig")<< " " << *sp << " in sector "<<sp->msSector()->identString() << " lay "<<m_spSorter.sectorLayerNum(*sp));
460 }
461 }
462 if (sp->measuresPhi() && (!isTruthInfo || isSecondaryMatched)) {
463 ++phiCount;
465 ATH_MSG_VERBOSE("---> "<<"Phi " << *sp << " in sector "<<sp->msSector()->identString() << " lay "<<m_spSorter.sectorLayerNum(*sp));
466 }
467 }
468 };
469 const auto stIdx = Acts::toUnderlying(hitSt);
470 switch (type) {
471 case eReco:
472 updateCounts(m_pat_nNonPrecMeas[patIdx][stIdx],
473 m_pat_nPrecMeas[patIdx][stIdx], m_pat_nPhiMeas[patIdx][stIdx]);
474 return;
475 case eTruth:
476 updateCounts(m_pat_nTruthNonPrecMeas[patIdx][stIdx],
477 m_pat_nTruthPrecMeas[patIdx][stIdx], m_pat_nTruthPhiMeas[patIdx][stIdx]);
478 return;
479 case eMismatched:
480 updateCounts(m_pat_nMisTruthNonPrecMeas[patIdx][stIdx],
481 m_pat_nMisTruthPrecMeas[patIdx][stIdx], m_pat_nMisTruthPhiMeas[patIdx][stIdx]);
482 return;
483 case eAll:
484 updateCounts(m_pat_nAllNonPrecMeas[patIdx][stIdx],
485 m_pat_nAllPrecMeas[patIdx][stIdx], m_pat_nAllPhiMeas[patIdx][stIdx]);
486 return;
487 case ePileup:
488 updateCounts(m_pat_nPileupNonPrecMeas[patIdx][stIdx],
489 m_pat_nPileupPrecMeas[patIdx][stIdx], m_pat_nPileupPhiMeas[patIdx][stIdx]);
490 return;
491 }
492 }
493} // namespace MuonValR4
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
std::vector< size_t > vec
static Double_t sp
static Double_t a
size_t size() const
Number of registered mappings.
size_type size() const noexcept
Returns the number of elements in the collection.
bool empty() const noexcept
Returns true if the collection is empty.
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...
void fillTruthInfo(const TruthParticleMap &truthHits, const std::vector< const MuonR4::SpacePointContainer * > &spContainers)
Fill the truth particle information into the tree.
MuonVal::VectorBranch< float > & m_gen_Phi
MuonVal::MatrixBranch< unsigned char > & m_pat_nAllNonPrecMeas
Number of trigger eta measurements in the buckets crossed by the pattern, grouped by station.
MuonVal::VectorBranch< unsigned char > & m_spType
Type of spacepoints: 1 for trigger eta, 2 for precision, 3 for only-phi.
MuonVal::VectorBranch< float > & m_roi_ZMax
SG::ReadHandleKey< MuonR4::SpacePointContainer > m_NSWspKey
MuonVal::MatrixBranch< unsigned char > & m_pat_nNonPrecMeas
Number of trigger eta measurements per station.
measType
Enum for measurement types.
MuonVal::MatrixBranch< unsigned char > & m_pat_nAllPhiMeas
Number of phi measurements in the buckets crossed by the pattern, grouped by station.
MuonVal::MatrixBranch< unsigned char > & m_pat_nTruthPrecMeas
Number of truth precision measurements per station.
SG::ReadHandleKey< MuonR4::GlobalPatternContainer > m_patternKey
MuonVal::ScalarBranch< unsigned > & m_pat_n
====== Global Pattern block ===========
MuonVal::MatrixBranch< unsigned char > & m_spMatchedToPattern
Branch indicating which space points in the tree are associated to the i-th pattern.
MuonVal::MatrixBranch< unsigned char > & m_pat_nMisTruthPhiMeas
Number of mismatched truth phi measurements per station.
MuonVal::VectorBranch< unsigned char > & m_pat_nStations
Number of stations.
MuonVal::MatrixBranch< unsigned char > & m_NSWspMatchedToTruth
MuonVal::MatrixBranch< unsigned char > & m_pat_nPileupPhiMeas
Number of pileup phi measurements per station.
void fillRoIInfo(const TrigRoiDescriptorCollection *roiCollection)
Fill the RoI information into the tree.
MuonVal::VectorBranch< uint16_t > & m_pat_sector2
MuonVal::VectorBranch< float > & m_gen_Eta
MuonVal::MatrixBranch< unsigned char > & m_pat_nAllPrecMeas
Number of precision measurements in the buckets crossed by the pattern, grouped by station.
MuonVal::MatrixBranch< unsigned char > & m_pat_nPileupPrecMeas
Number of pileup precision measurements per station.
MuonVal::VectorBranch< float > & m_pat_phi
virtual StatusCode execute() override
SG::ReadHandleKey< TrigRoiDescriptorCollection > m_roiCollectionKey
std::map< const xAOD::TruthParticle *, std::vector< simHitSet > > TruthParticleMap
MuonVal::VectorBranch< short > & m_gen_Q
====== Truth particle block ===========
SG::ReadHandleKey< ActsTrk::GeometryContext > m_geoCtxKey
virtual StatusCode finalize() override
MuonVal::MatrixBranch< unsigned char > & m_gen_nPrecMeas
Number of precision measurements per station.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
void updatePatHitInfo(const ePatBranchType type, const std::size_t patIdx, const Muon::MuonStationIndex::StIndex hitSt, const MuonR4::SpacePoint *sp, const bool isSecondaryMatched=false)
Update the hit counts for a given pattern branch type.
ePatBranchType
Enum for different types of pattern hit content branches.
SG::ReadHandleKey< xAOD::MuonSegmentContainer > m_truthSegmentKey
MuonVal::VectorBranch< float > & m_roi_EtaMin
====== RoI info ===========
MuonVal::MatrixBranch< unsigned char > & m_pat_nTruthPhiMeas
Number of truth phi measurements per station.
std::shared_ptr< SpacePointTesterModule > m_NSWspTester
MuonVal::VectorBranch< float > & m_roi_PhiMin
MuonVal::VectorBranch< float > & m_roi_PhiMax
std::shared_ptr< SpacePointTesterModule > m_spTester
====== Spacepoint block ===========
MuonVal::MatrixBranch< unsigned char > & m_pat_nTruthNonPrecMeas
Number of truth trigger eta measurements per station.
virtual StatusCode initialize() override
MuonVal::MatrixBranch< unsigned char > & m_pat_nPhiMeas
Number of phi measurements per station.
MuonVal::MatrixBranch< unsigned char > & m_pat_nPrecMeas
Number of precision measurements per station.
MuonVal::VectorBranch< float > & m_roi_EtaMax
MuonVal::VectorBranch< float > & m_pat_meanNormResidual2
mean square normalized pattern residual
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::MatrixBranch< unsigned char > & m_pat_nMisTruthNonPrecMeas
Number of mismatched truth trigger eta measurements per station.
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::MatrixBranch< unsigned char > & m_pat_nMisTruthPrecMeas
Number of mismatched truth precision measurements per station.
MuonVal::MuonTesterTree m_tree
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.
MuonR4::SpacePointPerLayerSorter m_spSorter
MuonVal::MatrixBranch< unsigned char > & m_spMatchedToTruth
Branch indicating which space points in the tree are associated to the i-th truth particle.
MuonVal::MatrixBranch< unsigned char > & m_gen_nPhiMeas
Number of phi measurements per station.
MuonVal::MatrixBranch< unsigned char > & m_pat_nPileupNonPrecMeas
Number of pileup trigger eta measurements per station.
MuonVal::VectorBranch< float > & m_pat_Eta
pattern average theta & phi
MuonVal::MatrixBranch< unsigned char > & m_gen_nNonPrecMeas
Number of trigger eta measurements per station.
SG::ReadHandleKey< MuonR4::SpacePointContainer > m_spKey
TruthParticleMap fillTruthMap(const xAOD::MuonSegmentContainer *truthSegments, const TrigRoiDescriptorCollection *roiCollection) const
Fill the truth particle map.
MuonVal::VectorBranch< float > & m_roi_ZMin
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.
void getSectors(double phi, std::vector< int > &sectors) const
returns the main sector plus neighboring if the phi position is in an overlap region
nope - should be used for standalone also, perhaps need to protect the class def bits ifndef XAOD_ANA...
STL class.
T deltaPhi(T phiA, T phiB)
Return difference phiA - phiB in range [-pi, pi].
Definition phihelper.h:42
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
const xAOD::MuonSimHit * getTruthMatchedHit(const xAOD::MuonMeasurement &prdHit)
Returns the MuonSimHit, if there's any, matched to the uncalibrated muon measurement.
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::unordered_set< const xAOD::MuonSimHit * > simHitSet
bool isInPattern(const SpacePoint *sp, const StIndex station, const GlobalPattern &pattern)
std::map< const xAOD::TruthParticle *, std::vector< simHitSet > > TruthParticleMap
constexpr std::size_t s_nStations
std::optional< std::size_t > isTruthMatched(const xAOD::MuonMeasurement &meas, const TruthParticleMap &truthHits)
StIndex
enum to classify the different station layers in the muon spectrometer
const std::string & stName(StIndex index)
convert StIndex into a string
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".
MuonMeasurement_v1 MuonMeasurement
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:
Helper for azimuthal angle calculations.