Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-20 07:35:25

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include "ActsExamples/Validation/TrackClassification.hpp"
0010 
0011 #include "ActsExamples/EventData/IndexSourceLink.hpp"
0012 #include "ActsExamples/EventData/SimParticle.hpp"
0013 #include "ActsExamples/EventData/Track.hpp"
0014 #include "ActsExamples/EventData/Trajectories.hpp"
0015 #include "ActsExamples/Utilities/Range.hpp"
0016 
0017 #include <algorithm>
0018 
0019 namespace ActsExamples {
0020 
0021 namespace {
0022 
0023 /// Increase the hit count for the given particle id by one.
0024 inline void increaseHitCount(std::vector<ParticleHitCount>& particleHitCounts,
0025                              SimBarcode particleId) {
0026   // linear search since there is no ordering
0027   auto it = std::ranges::find_if(particleHitCounts, [=](const auto& phc) {
0028     return (phc.particleId == particleId);
0029   });
0030   // either increase count if we saw the particle before or add it
0031   if (it != particleHitCounts.end()) {
0032     it->hitCount += 1u;
0033   } else {
0034     particleHitCounts.push_back({particleId, 1u});
0035   }
0036 }
0037 
0038 /// Sort hit counts by decreasing values, i.e. majority particle comes first.
0039 inline void sortHitCount(std::vector<ParticleHitCount>& particleHitCounts) {
0040   std::ranges::sort(particleHitCounts, std::greater{},
0041                     [](const auto& p) { return p.hitCount; });
0042 }
0043 
0044 }  // namespace
0045 
0046 }  // namespace ActsExamples
0047 
0048 void ActsExamples::identifyContributingParticles(
0049     const MeasurementParticlesMap& measurementParticlesMap,
0050     const ProtoTrack& protoTrack,
0051     std::vector<ParticleHitCount>& particleHitCounts) {
0052   particleHitCounts.clear();
0053 
0054   for (auto hitIndex : protoTrack) {
0055     // register all particles that generated this hit
0056     for (const auto& [_, value] :
0057          makeRange(measurementParticlesMap.equal_range(hitIndex))) {
0058       increaseHitCount(particleHitCounts, value);
0059     }
0060   }
0061   sortHitCount(particleHitCounts);
0062 }
0063 
0064 void ActsExamples::identifyContributingParticles(
0065     const MeasurementParticlesMap& measurementParticlesMap,
0066     const Trajectories& trajectories, std::size_t tip,
0067     std::vector<ParticleHitCount>& particleHitCounts) {
0068   particleHitCounts.clear();
0069 
0070   if (!trajectories.hasTrajectory(tip)) {
0071     return;
0072   }
0073 
0074   trajectories.multiTrajectory().visitBackwards(tip, [&](const auto& state) {
0075     // no truth info with non-measurement state
0076     if (!state.typeFlags().isMeasurement()) {
0077       return true;
0078     }
0079     // skip outliers
0080     if (state.typeFlags().isOutlier()) {
0081       return true;
0082     }
0083     // register all particles that generated this hit
0084     IndexSourceLink sl =
0085         state.getUncalibratedSourceLink().template get<IndexSourceLink>();
0086     auto hitIndex = sl.index();
0087     for (const auto& [_, value] :
0088          makeRange(measurementParticlesMap.equal_range(hitIndex))) {
0089       increaseHitCount(particleHitCounts, value);
0090     }
0091     return true;
0092   });
0093   sortHitCount(particleHitCounts);
0094 }
0095 
0096 void ActsExamples::identifyContributingParticles(
0097     const MeasurementParticlesMap& measurementParticlesMap,
0098     const ConstTrackContainer::ConstTrackProxy& track,
0099     std::vector<ParticleHitCount>& particleHitCounts) {
0100   particleHitCounts.clear();
0101 
0102   for (const auto& state : track.trackStatesReversed()) {
0103     // no truth info with non-measurement state
0104     if (!state.typeFlags().isMeasurement()) {
0105       continue;
0106     }
0107     // skip outliers
0108     if (state.typeFlags().isOutlier()) {
0109       continue;
0110     }
0111     if (state.getUncalibratedSourceLink().template getPtr<IndexSourceLink>() ==
0112         nullptr) {
0113       continue;
0114     }
0115     // register all particles that generated this hit
0116     IndexSourceLink sl =
0117         state.getUncalibratedSourceLink().template get<IndexSourceLink>();
0118     auto hitIndex = sl.index();
0119     for (const auto& [_, value] :
0120          makeRange(measurementParticlesMap.equal_range(hitIndex))) {
0121       increaseHitCount(particleHitCounts, value);
0122     }
0123   }
0124   sortHitCount(particleHitCounts);
0125 }