ATLAS Offline Software
Loading...
Searching...
No Matches
TrackToTruthAssociationAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
8
11
12#include <iomanip>
13#include <cmath>
14#include <type_traits>
15#include <typeinfo>
16#include <numeric>
17
18
19namespace ActsTrk
20{
21 // to dump
22 inline MsgStream &operator<<(MsgStream &out, const ActsUtils::Stat &stat) {
23 ActsUtils::dumpStat(out, stat);
24 return out;
25 }
26
28 {
29 ATH_CHECK( m_ctxProvider.initialize() );
30 ATH_CHECK( m_tracksContainerKey.initialize() );
31 ATH_CHECK( m_measAssocKeys.initialize() );
32 ATH_CHECK( m_trackToTruthOut.initialize() );
33
34 m_elasticDecayUtil.setEnergyLossBinning(m_energyLossBinning.value());
35 return StatusCode::SUCCESS;
36 }
37
38 template <bool IsDebug>
39 template <class T_OutStream>
41 if constexpr(IsDebug) {
42 out << "Measurements per track :" << m_measPerTrack << std::endl
43 << m_measPerTrack.histogramToString() << std::endl
44 << "TruthParticles per track :" << m_truthParticlesPerTrack << std::endl
45 << m_truthParticlesPerTrack.histogramToString();
46 }
47 }
48 template <bool IsDebug>
49 void inline TrackToTruthAssociationAlg::AssociationCounter<IsDebug>::fillStatistics(unsigned int n_measurements, unsigned int n_particles) const {
50 if constexpr(IsDebug) {
51 std::lock_guard<std::mutex> lock(m_mutex);
52 m_measPerTrack.add(n_measurements);
53 m_truthParticlesPerTrack.add(n_particles);
54 }
55 }
56
57 namespace {
58 std::string makeLabel(const std::string &header, unsigned int i, const std::string &tail) {
59 std::stringstream label;
60 label << header << " " << i << " " << tail;
61 return label.str();
62 }
63 }
64
66 {
68 ATH_MSG_WARNING( "Encountered measurements not compaible with provided association maps in "
70 }
71 if (msgLvl(MSG::INFO)) {
72 msg(MSG::INFO) << "-- Statistics:" << std::endl;
73 unsigned int idx=0;
74 for (const std::atomic<std::size_t> &elm : m_nTracksWithAssociatedTruth) {
75 msg() << std::setw(20) << elm << " "
76 << (idx==0
77 ? std::string(" tracks without associated truth particles.")
78 : (idx==m_nTracksWithAssociatedTruth.size()-1
79 ? makeLabel(" tracks with more than",
80 m_nTracksWithAssociatedTruth.size()-1,
81 "associated truth particles.")
82 : makeLabel(" tracks with",
83 idx,
84 "associated truth particle(s).")));
85 if (idx!=m_nTracksWithAssociatedTruth.size()-1 || TrackToTruthParticleAssociationDebugHists) {
86 msg() << std::endl;
87 }
88 ++idx;
89 }
91 m_elasticDecayUtil.dumpStatistics(msg());
92 msg() << std::endl;
93 m_associationCounter.dumpStatistics(msg());
94 }
95 msg() << endmsg;
96 }
97 return StatusCode::SUCCESS;
98 }
99
100 StatusCode TrackToTruthAssociationAlg::execute(const EventContext &ctx) const
101 {
102 auto track_association = std::make_unique<TrackToTruthParticleAssociation>();
103
104 const ActsTrk::TrackContainer* tracksContainer{};
105 ATH_CHECK(SG::get(tracksContainer, m_tracksContainerKey, ctx));
106
107 track_association->resize( tracksContainer->size() );
108 track_association->setSourceContainer(DataLink<ActsTrk::TrackContainer>(*tracksContainer,ctx));
109 const Acts::GeometryContext tgContext = m_ctxProvider.getGeometryContext(ctx);
110
111 std::array<std::vector<const ActsTrk::MeasurementToTruthParticleAssociation*>,
112 Acts::toUnderlying(xAOD::UncalibMeasType::nTypes)> prdToTruthMaps{};
113
114 for (const auto& key : m_measAssocKeys) {
115 const MeasurementToTruthParticleAssociation* measAssocMap{};
116 ATH_CHECK(SG::get(measAssocMap, key, ctx));
117 if (measAssocMap->sourceContainer()->empty()) {
118 continue;
119 }
120 const xAOD::UncalibMeasType measType = measAssocMap->sourceContainer()->front()->type();
121 prdToTruthMaps[Acts::toUnderlying(measType)].push_back(measAssocMap);
122 }
123 std::array<unsigned int,s_NCounterForAssociatedTruth> tracks_with_associated_truth{};
124 std::pair<unsigned int, unsigned int> compatible_assoc_container_counts{};
126 // used to suppress reoccurring error messages
128 ++compatible_assoc_container_counts.second;
129 }
130
131 std::vector<unsigned int> counted_truth_particles;
132 counted_truth_particles.reserve(10);
133
134 for (const typename ActsTrk::TrackContainer::ConstTrackProxy track : *tracksContainer) {
135 const unsigned track_i = track.index();
136 unsigned int n_measurements=0u;
137
138 HitCounterArray &reco_hits = track_association->at(track_i).totalCounts();
139 HitCounterArray &noise_hits = track_association->at(track_i).noiseCounts();
140 ActsTrk::HitCountsPerTrack::container &truth_particle_counts = track_association->at(track_i).countsPerTruthParticle();
141 for (const typename ActsTrk::TrackStateBackend::ConstTrackStateProxy &state : track.trackStatesReversed()) {
142 if (state.typeFlags().isOutlier() || !state.hasUncalibratedSourceLink()) {
143 continue;
144 }
145 const auto* uncalibMeas = detail::xAODUncalibMeasCalibrator::unpack(state.getUncalibratedSourceLink());
146 const auto typeIdx = Acts::toUnderlying(uncalibMeas->type());
147
148 ++n_measurements;
149
150 const ActsTrk::MeasurementToTruthParticleAssociation* association_map{};
151 if (auto map_itr = std::ranges::find_if(prdToTruthMaps.at(typeIdx),
152 [uncalibMeas](const auto* map){
153 return uncalibMeas->container() == map->sourceContainer();
154 }); map_itr != prdToTruthMaps.at(typeIdx).end()) {
155 association_map = (*map_itr);
156 } else {
157 continue;
158 }
159 ++compatible_assoc_container_counts.second;
161 if (association_map->at(uncalibMeas->index()).empty()) {
162 ++noise_hits.at(typeIdx);
163 }
164 counted_truth_particles.clear();
166 for (const xAOD::TruthParticle *truth_particle : association_map->at(uncalibMeas->index()) ) {
167 const xAOD::TruthParticle *mother_particle = m_elasticDecayUtil.getMother(*truth_particle, m_maxEnergyLoss.value());
168 ATH_MSG_VERBOSE("Fill truth counts for "<<uncalibMeas->type()<<" hit with particle "<<(mother_particle->pt()*1.e-3)<<" [GeV], eta:"
169 <<mother_particle->eta()<<", " <<", phi: "<<mother_particle->phi()<<", pdgId: "<<mother_particle->pdgId()<<", index: "<<mother_particle->index()
170 <<", "<<mother_particle->container());
171 // do not count hits of associated truth particles again if they are associated to the same elastic decay chain:
172 if (!Acts::rangeContainsValue(counted_truth_particles, mother_particle->index())) {
173 counted_truth_particles.push_back(mother_particle->index());
174
175 ActsTrk::HitCountsPerTrack::container::iterator
176 hit_count_iter = std::ranges::find_if(truth_particle_counts,
177 [mother_particle](const std::pair<const xAOD::TruthParticle *, HitCounterArray > &a) {
178 return a.first == mother_particle;
179 });
180 if (hit_count_iter == truth_particle_counts.end()) {
181 truth_particle_counts.push_back( std::make_pair(mother_particle, HitCounterArray{}));
182 hit_count_iter = truth_particle_counts.end()-1;
183 }
184 ++(hit_count_iter->second.at(typeIdx));
185 }
186 }
187 ++reco_hits.at(typeIdx);
188 }
189 std::ranges::stable_sort(truth_particle_counts,
190 [](const std::pair<const xAOD::TruthParticle*, HitCounterArray>& a,
191 const std::pair<const xAOD::TruthParticle*, HitCounterArray>& b) {
192 return std::accumulate(a.second.begin(),a.second.end(),0u) >
193 std::accumulate(b.second.begin(),b.second.end(),0u);
194 });
195 m_associationCounter.fillStatistics(n_measurements, truth_particle_counts.size());
196 ++(tracks_with_associated_truth[std::min(truth_particle_counts.size(),
197 tracks_with_associated_truth.size()-1u)]);
198 }
199 for (const auto[idx, elem] : Acts::enumerate(tracks_with_associated_truth)) {
200 m_nTracksWithAssociatedTruth[idx] += elem;
201
202 }
203 m_nIncompatibleMeasurementContainer += compatible_assoc_container_counts.second;
204 m_nCcompatibleMeasurementContainer += compatible_assoc_container_counts.first;
205
206 SG::WriteHandle associationOutHandle{m_trackToTruthOut, ctx};
207 ATH_CHECK(associationOutHandle.record( std::move(track_association)));
208 return StatusCode::SUCCESS;
209 }
210
211} // namespace
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
static Double_t a
boost::container::small_vector< std::pair< const xAOD::TruthParticle *, HitCounterArray >, NTruthParticlesPerTrack > container
const xAOD::UncalibratedMeasurementContainer * sourceContainer() const
std::atomic< std::size_t > m_nCcompatibleMeasurementContainer
AssociationCounter< TrackToTruthParticleAssociationDebugHists > m_associationCounter
SG::WriteHandleKey< TrackToTruthParticleAssociation > m_trackToTruthOut
std::atomic< std::size_t > m_nIncompatibleMeasurementContainer
SG::ReadHandleKey< ActsTrk::TrackContainer > m_tracksContainerKey
virtual StatusCode execute(const EventContext &ctx) const override
Gaudi::Property< std::vector< float > > m_energyLossBinning
ContextUtility m_ctxProvider
Context provider for geometry, magnetic field and calibration contexts.
SG::ReadHandleKeyArray< MeasurementToTruthParticleAssociation > m_measAssocKeys
ElasticDecayUtil< TrackToTruthParticleAssociationDebugHists > m_elasticDecayUtil
static const xAOD::UncalibratedMeasurement * unpack(const Acts::SourceLink &sl)
Helper method to unpack an Acts source link to an uncalibrated measurement.
Simple class to gather statistics : min, max, mean, rms.
Definition StatUtils.h:17
bool msgLvl(const MSG::Level lvl) const
const T * front() const
Access the first element in the collection as an rvalue.
bool empty() const noexcept
Returns true if the collection is empty.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
STL class.
int pdgId() const
PDG ID code.
virtual double pt() const override final
The transverse momentum ( ) of the particle.
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
virtual double phi() const override final
The azimuthal angle ( ) of the particle.
virtual xAOD::UncalibMeasType type() const =0
Returns the type of the measurement type as a simple enumeration.
std::string tail(std::string s, const std::string &pattern)
tail of a string
std::string label(const std::string &format, int i)
Definition label.h:19
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
std::ostream & operator<<(std::ostream &ostr, const DetectorType type)
Pipe the detector type to an outstream object.
constexpr bool TrackToTruthParticleAssociationDebugHists
std::array< uint8_t, NHitCounter > HitCounterArray
void dumpStat(T_Stream &out, const Stat &stat)
Dump the given statistics object to the given output stream.
Definition StatUtils.h:63
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
TruthParticle_v1 TruthParticle
Typedef to implementation.
UncalibMeasType
Define the type of the uncalibrated measurement.
void fillStatistics(unsigned int n_measurements, unsigned int n_particles) const