ATLAS Offline Software
Loading...
Searching...
No Matches
TrackToTruthAssociationAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6
8
11#include <iomanip>
12#include <cmath>
13#include <type_traits>
14#include <typeinfo>
15#include <numeric>
16
17
18namespace ActsTrk
19{
20 // to dump
21 inline MsgStream &operator<<(MsgStream &out, const ActsUtils::Stat &stat) {
22 ActsUtils::dumpStat(out, stat);
23 return out;
24 }
25
27 ISvcLocator *pSvcLocator)
28 : AthReentrantAlgorithm(name, pSvcLocator)
29 {
30 }
31
33 {
35 ATH_CHECK( m_tracksContainerKey.initialize() );
36 ATH_CHECK( m_pixelClustersToTruth.initialize() );
37 ATH_CHECK( m_stripClustersToTruth.initialize() );
38 if (!m_hgtdClustersToTruth.key().empty()) ATH_CHECK( m_hgtdClustersToTruth.initialize() );
39 ATH_CHECK( m_trackToTruthOut.initialize() );
40
41 m_elasticDecayUtil.setEnergyLossBinning(m_energyLossBinning.value());
42 return StatusCode::SUCCESS;
43 }
44
45 template <bool IsDebug>
46 template <class T_OutStream>
48 if constexpr(IsDebug) {
49 out << "Measurements per track :" << m_measPerTrack << std::endl
50 << m_measPerTrack.histogramToString() << std::endl
51 << "TruthParticles per track :" << m_truthParticlesPerTrack << std::endl
52 << m_truthParticlesPerTrack.histogramToString();
53 }
54 }
55 template <bool IsDebug>
56 void inline TrackToTruthAssociationAlg::AssociationCounter<IsDebug>::fillStatistics(unsigned int n_measurements, unsigned int n_particles) const {
57 if constexpr(IsDebug) {
58 std::lock_guard<std::mutex> lock(m_mutex);
59 m_measPerTrack.add(n_measurements);
60 m_truthParticlesPerTrack.add(n_particles);
61 }
62 }
63
64 namespace {
65 std::string makeLabel(const std::string &header, unsigned int i, const std::string &tail) {
66 std::stringstream label;
67 label << header << " " << i << " " << tail;
68 return label.str();
69 }
70 }
71
73 {
75 ATH_MSG_WARNING( "Encountered measurements not compaible with provided association maps in "
77 }
78 if (msgLvl(MSG::INFO)) {
79 msg(MSG::INFO) << "-- Statistics:" << std::endl;
80 unsigned int idx=0;
81 for (const std::atomic<std::size_t> &elm : m_nTracksWithAssociatedTruth) {
82 msg() << std::setw(20) << elm << " "
83 << (idx==0
84 ? std::string(" tracks without associated truth particles.")
85 : (idx==m_nTracksWithAssociatedTruth.size()-1
86 ? makeLabel(" tracks with more than",
87 m_nTracksWithAssociatedTruth.size()-1,
88 "associated truth particles.")
89 : makeLabel(" tracks with",
90 idx,
91 "associated truth particle(s).")));
92 if (idx!=m_nTracksWithAssociatedTruth.size()-1 || TrackToTruthParticleAssociationDebugHists) {
93 msg() << std::endl;
94 }
95 ++idx;
96 }
98 m_elasticDecayUtil.dumpStatistics(msg());
99 msg() << std::endl;
100 m_associationCounter.dumpStatistics(msg());
101 }
102 msg() << endmsg;
103 }
104 return StatusCode::SUCCESS;
105 }
106
107 StatusCode TrackToTruthAssociationAlg::execute(const EventContext &ctx) const
108 {
109 std::unique_ptr<TrackToTruthParticleAssociation>
110 track_association( std::make_unique<TrackToTruthParticleAssociation>() );
111
113 if (!pixelClustersToTruthAssociation.isValid()) {
114 ATH_MSG_ERROR("No pixel clusterss for key " << m_pixelClustersToTruth.key() );
115 return StatusCode::FAILURE;
116 }
118 if (!stripClustersToTruthAssociation.isValid()) {
119 ATH_MSG_ERROR("No strip clusterss for key " << m_stripClustersToTruth.key() );
120 return StatusCode::FAILURE;
121 }
122
124 if (!tracksContainer.isValid()) {
125 ATH_MSG_ERROR("No tracks for key " << m_tracksContainerKey.key() );
126 return StatusCode::FAILURE;
127 }
128 track_association->resize( tracksContainer->size() );
129 track_association->setSourceContainer(DataLink<ActsTrk::TrackContainer>(*tracksContainer,ctx));
130 Acts::GeometryContext tgContext = m_trackingGeometryTool->getGeometryContext(ctx).context();
131
133 static_cast< std::underlying_type<xAOD::UncalibMeasType>::type >(xAOD::UncalibMeasType::nTypes)>
134 measurement_to_truth_association_maps{};
135
136 measurement_to_truth_association_maps[Acts::toUnderlying(xAOD::UncalibMeasType::PixelClusterType)]=pixelClustersToTruthAssociation.cptr();
137 measurement_to_truth_association_maps[Acts::toUnderlying(xAOD::UncalibMeasType::StripClusterType)]=stripClustersToTruthAssociation.cptr();
138
139 if (!m_hgtdClustersToTruth.key().empty()) {
141 if (!hgtdClustersToTruthAssociation.isValid()) {
142 ATH_MSG_DEBUG("No HGTD clusterss for key " << m_hgtdClustersToTruth.key() );
143 }
144 measurement_to_truth_association_maps[Acts::toUnderlying(xAOD::UncalibMeasType::HGTDClusterType)]=hgtdClustersToTruthAssociation.cptr();
145 }
146
147 auto assocSize = [&measurement_to_truth_association_maps](xAOD::UncalibMeasType type) {
148 const ActsTrk::MeasurementToTruthParticleAssociation *assoc = measurement_to_truth_association_maps[Acts::toUnderlying(type)];
149 return assoc ? assoc->size() : 0ul;
150 };
151
152 ATH_MSG_DEBUG("Measurement association entries: " << assocSize(xAOD::UncalibMeasType::PixelClusterType)
153 << " + " << assocSize(xAOD::UncalibMeasType::StripClusterType)
154 << " + " << assocSize(xAOD::UncalibMeasType::HGTDClusterType)
155 );
156 unsigned int track_i=0;
157 std::array<unsigned int,s_NCounterForAssociatedTruth> tracks_with_associated_truth{};
158 std::pair<unsigned int, unsigned int> compatible_assoc_container_counts{};
160 // used to suppress reoccurring error messages
162 ++compatible_assoc_container_counts.second;
163 }
164
165 std::vector<unsigned int> counted_truth_particles;
166 counted_truth_particles.reserve(10);
167
168 for (const typename ActsTrk::TrackContainer::ConstTrackProxy track : *tracksContainer) {
169 const auto lastMeasurementIndex = track.tipIndex();
170
171 unsigned int n_measurements=0u;
172
173 HitCounterArray &reco_hits = track_association->at(track_i).totalCounts();
174 HitCounterArray &noise_hits = track_association->at(track_i).noiseCounts();
175 ActsTrk::HitCountsPerTrack::container &truth_particle_counts = track_association->at(track_i).countsPerTruthParticle();
176 tracksContainer->trackStateContainer().visitBackwards(
177 lastMeasurementIndex,
178 [this,
179 &n_measurements,
180 &measurement_to_truth_association_maps,
181 &truth_particle_counts,
182 &reco_hits,
183 &noise_hits,
184 &counted_truth_particles,
185 &compatible_assoc_container_counts
186 ](const typename ActsTrk::TrackStateBackend::ConstTrackStateProxy &state) -> void
187 {
188 if (!state.typeFlags().isOutlier() && state.hasUncalibratedSourceLink()) {
189 const auto* uncalibMeas = detail::xAODUncalibMeasCalibrator::unpack(state.getUncalibratedSourceLink());
190
191 const ActsTrk::MeasurementToTruthParticleAssociation *association_map = measurement_to_truth_association_maps.at(Acts::toUnderlying(uncalibMeas->type()));
192 if (association_map) {
193 if (!association_map->isCompatibleWith(dynamic_cast< const xAOD::UncalibratedMeasurementContainer *>(uncalibMeas->container()))) {
194 if (compatible_assoc_container_counts.second==0) {
195 ATH_MSG_ERROR("MeasurementToTruthParticleAssociation for measurement type " << uncalibMeas->type()
196 << " is not compatible with the measurement on track.");
197 }
198 ++compatible_assoc_container_counts.second;
199 return;
200 }
201 else {
202 ++compatible_assoc_container_counts.first;
203 }
204 ++n_measurements;
205 counted_truth_particles.clear();
206 for (const xAOD::TruthParticle *truth_particle : association_map->at(uncalibMeas->index()) ) {
207 const xAOD::TruthParticle *mother_particle = m_elasticDecayUtil.getMother(*truth_particle, m_maxEnergyLoss.value());
208
209 // do not count hits of associated truth particles again if they are associated to the same elastic decay chain:
210 if (std::find(counted_truth_particles.begin(), counted_truth_particles.end(), mother_particle->index())
211 ==counted_truth_particles.end()) {
212 counted_truth_particles.push_back(mother_particle->index());
213
214 ActsTrk::HitCountsPerTrack::container::iterator
215 hit_count_iter = std::find_if(truth_particle_counts.begin(),
216 truth_particle_counts.end(),
217 [mother_particle](const std::pair<const xAOD::TruthParticle *, HitCounterArray > &a) {
218 return a.first == mother_particle;
219 });
220 if (hit_count_iter == truth_particle_counts.end()) {
221 truth_particle_counts.push_back( std::make_pair(mother_particle, HitCounterArray{}));
222 hit_count_iter = truth_particle_counts.end()-1;
223 }
224 ++(hit_count_iter->second.at( Acts::toUnderlying(uncalibMeas->type())));
225 }
226 }
227 if (association_map->at(uncalibMeas->index()).empty()) {
228 ++noise_hits.at( Acts::toUnderlying(uncalibMeas->type()));
229 }
230 }
231 ++reco_hits.at( Acts::toUnderlying(uncalibMeas->type()));
232 }
233
234 });
235 std::sort( truth_particle_counts.begin(),
236 truth_particle_counts.end(),
237 [](const std::pair<const xAOD::TruthParticle *, HitCounterArray > &a,
238 const std::pair<const xAOD::TruthParticle *, HitCounterArray > &b) {
239 return std::accumulate(a.second.begin(),a.second.end(),0u) > std::accumulate(b.second.begin(),b.second.end(),0u);
240 });
241 m_associationCounter.fillStatistics(n_measurements, truth_particle_counts.size());
242 ++(tracks_with_associated_truth[std::min(truth_particle_counts.size(),tracks_with_associated_truth.size()-1u)]);
243 ++track_i;
244 }
245 unsigned int idx=0;
246 for (unsigned int elm : tracks_with_associated_truth) {
247 m_nTracksWithAssociatedTruth[idx] += elm;
248 ++idx;
249 }
250 m_nIncompatibleMeasurementContainer += compatible_assoc_container_counts.second;
251 m_nCcompatibleMeasurementContainer += compatible_assoc_container_counts.first;
252
254 if (associationOutHandle.record( std::move(track_association)).isFailure()) {
255 ATH_MSG_ERROR("Failed to record track to truth assocition with key " << m_trackToTruthOut.key() );
256 return StatusCode::FAILURE;
257 }
258 return StatusCode::SUCCESS;
259 }
260
261} // namespace
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(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
bool isCompatibleWith(const xAOD::UncalibratedMeasurementContainer *container) const
std::atomic< std::size_t > m_nCcompatibleMeasurementContainer
AssociationCounter< TrackToTruthParticleAssociationDebugHists > m_associationCounter
PublicToolHandle< ActsTrk::ITrackingGeometryTool > m_trackingGeometryTool
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
std::conditional< TrackToTruthParticleAssociationDebugHists, Gaudi::Property< std::vector< float > >, EmptyProperty >::type m_energyLossBinning
SG::ReadHandleKey< MeasurementToTruthParticleAssociation > m_hgtdClustersToTruth
ElasticDecayUtil< TrackToTruthParticleAssociationDebugHists > m_elasticDecayUtil
SG::ReadHandleKey< MeasurementToTruthParticleAssociation > m_pixelClustersToTruth
TrackToTruthAssociationAlg(const std::string &name, ISvcLocator *pSvcLocator)
SG::ReadHandleKey< MeasurementToTruthParticleAssociation > m_stripClustersToTruth
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
An algorithm that can be simultaneously executed in multiple threads.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
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
void dumpStat(T_Stream &out, const Stat &stat)
Dump the given statistics object to the given output stream.
Definition StatUtils.h:63
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
TruthParticle_v1 TruthParticle
Typedef to implementation.
UncalibMeasType
Define the type of the uncalibrated measurement.
UncalibratedMeasurementContainer_v1 UncalibratedMeasurementContainer
Define the version of the uncalibrated measurement container.
void fillStatistics(unsigned int n_measurements, unsigned int n_particles) const