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