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
10#include <iomanip>
11#include <cmath>
12#include <type_traits>
13#include <typeinfo>
14#include <numeric>
15
16namespace {
17 template <typename T_EnumClass >
18 constexpr typename std::underlying_type<T_EnumClass>::type to_underlying(T_EnumClass an_enum) {
19 return static_cast<typename std::underlying_type<T_EnumClass>::type>(an_enum);
20 }
21}
22namespace ActsTrk
23{
24 // to dump
25 inline MsgStream &operator<<(MsgStream &out, const ActsUtils::Stat &stat) {
26 ActsUtils::dumpStat(out, stat);
27 return out;
28 }
29
31 ISvcLocator *pSvcLocator)
32 : AthReentrantAlgorithm(name, pSvcLocator)
33 {
34 }
35
37 {
39 ATH_CHECK( m_tracksContainerKey.initialize() );
40 ATH_CHECK( m_pixelClustersToTruth.initialize() );
41 ATH_CHECK( m_stripClustersToTruth.initialize() );
42 if (!m_hgtdClustersToTruth.key().empty()) ATH_CHECK( m_hgtdClustersToTruth.initialize() );
43 ATH_CHECK( m_trackToTruthOut.initialize() );
44
45 m_elasticDecayUtil.setEnergyLossBinning(m_energyLossBinning.value());
46 return StatusCode::SUCCESS;
47 }
48
49 template <bool IsDebug>
50 template <class T_OutStream>
52 if constexpr(IsDebug) {
53 out << "Measurements per track :" << m_measPerTrack << std::endl
54 << m_measPerTrack.histogramToString() << std::endl
55 << "TruthParticles per track :" << m_truthParticlesPerTrack << std::endl
56 << m_truthParticlesPerTrack.histogramToString();
57 }
58 }
59 template <bool IsDebug>
60 void inline TrackToTruthAssociationAlg::AssociationCounter<IsDebug>::fillStatistics(unsigned int n_measurements, unsigned int n_particles) const {
61 if constexpr(IsDebug) {
62 std::lock_guard<std::mutex> lock(m_mutex);
63 m_measPerTrack.add(n_measurements);
64 m_truthParticlesPerTrack.add(n_particles);
65 }
66 }
67
68 namespace {
69 std::string makeLabel(const std::string &header, unsigned int i, const std::string &tail) {
70 std::stringstream label;
71 label << header << " " << i << " " << tail;
72 return label.str();
73 }
74 }
75
77 {
79 ATH_MSG_WARNING( "Encountered measurements not compaible with provided association maps in "
81 }
82 if (msgLvl(MSG::INFO)) {
83 msg(MSG::INFO) << "-- Statistics:" << std::endl;
84 unsigned int idx=0;
85 for (const std::atomic<std::size_t> &elm : m_nTracksWithAssociatedTruth) {
86 msg() << std::setw(20) << elm << " "
87 << (idx==0
88 ? std::string(" tracks without associated truth particles.")
89 : (idx==m_nTracksWithAssociatedTruth.size()-1
90 ? makeLabel(" tracks with more than",
91 m_nTracksWithAssociatedTruth.size()-1,
92 "associated truth particles.")
93 : makeLabel(" tracks with",
94 idx,
95 "associated truth particle(s).")));
96 if (idx!=m_nTracksWithAssociatedTruth.size()-1 || TrackToTruthParticleAssociationDebugHists) {
97 msg() << std::endl;
98 }
99 ++idx;
100 }
102 m_elasticDecayUtil.dumpStatistics(msg());
103 msg() << std::endl;
104 m_associationCounter.dumpStatistics(msg());
105 }
106 msg() << endmsg;
107 }
108 return StatusCode::SUCCESS;
109 }
110
111 StatusCode TrackToTruthAssociationAlg::execute(const EventContext &ctx) const
112 {
113 std::unique_ptr<TrackToTruthParticleAssociation>
114 track_association( std::make_unique<TrackToTruthParticleAssociation>() );
115
117 if (!pixelClustersToTruthAssociation.isValid()) {
118 ATH_MSG_ERROR("No pixel clusterss for key " << m_pixelClustersToTruth.key() );
119 return StatusCode::FAILURE;
120 }
122 if (!stripClustersToTruthAssociation.isValid()) {
123 ATH_MSG_ERROR("No strip clusterss for key " << m_stripClustersToTruth.key() );
124 return StatusCode::FAILURE;
125 }
126
128 if (!tracksContainer.isValid()) {
129 ATH_MSG_ERROR("No tracks for key " << m_tracksContainerKey.key() );
130 return StatusCode::FAILURE;
131 }
132 track_association->resize( tracksContainer->size() );
133 track_association->setSourceContainer(DataLink<ActsTrk::TrackContainer>(*tracksContainer,ctx));
134 Acts::GeometryContext tgContext = m_trackingGeometryTool->getGeometryContext(ctx).context();
135
137 static_cast< std::underlying_type<xAOD::UncalibMeasType>::type >(xAOD::UncalibMeasType::nTypes)>
138 measurement_to_truth_association_maps{};
139
140 measurement_to_truth_association_maps[to_underlying(xAOD::UncalibMeasType::PixelClusterType)]=pixelClustersToTruthAssociation.cptr();
141 measurement_to_truth_association_maps[to_underlying(xAOD::UncalibMeasType::StripClusterType)]=stripClustersToTruthAssociation.cptr();
142
143 if (!m_hgtdClustersToTruth.key().empty()) {
145 if (!hgtdClustersToTruthAssociation.isValid()) {
146 ATH_MSG_DEBUG("No HGTD clusterss for key " << m_hgtdClustersToTruth.key() );
147 }
148 measurement_to_truth_association_maps[to_underlying(xAOD::UncalibMeasType::HGTDClusterType)]=hgtdClustersToTruthAssociation.cptr();
149 }
150
151 auto assocSize = [&measurement_to_truth_association_maps](xAOD::UncalibMeasType type) {
152 const ActsTrk::MeasurementToTruthParticleAssociation *assoc = measurement_to_truth_association_maps[to_underlying(type)];
153 return assoc ? assoc->size() : 0ul;
154 };
155
156 ATH_MSG_DEBUG("Measurement association entries: " << assocSize(xAOD::UncalibMeasType::PixelClusterType)
157 << " + " << assocSize(xAOD::UncalibMeasType::StripClusterType)
158 << " + " << assocSize(xAOD::UncalibMeasType::HGTDClusterType)
159 );
160 unsigned int track_i=0;
161 std::array<unsigned int,s_NCounterForAssociatedTruth> tracks_with_associated_truth{};
162 std::pair<unsigned int, unsigned int> compatible_assoc_container_counts{};
164 // used to suppress reoccurring error messages
166 ++compatible_assoc_container_counts.second;
167 }
168
169 std::vector<unsigned int> counted_truth_particles;
170 counted_truth_particles.reserve(10);
171
172 for (const typename ActsTrk::TrackContainer::ConstTrackProxy track : *tracksContainer) {
173 const auto lastMeasurementIndex = track.tipIndex();
174
175 unsigned int n_measurements=0u;
176
177 HitCounterArray &reco_hits = track_association->at(track_i).totalCounts();
178 HitCounterArray &noise_hits = track_association->at(track_i).noiseCounts();
179 ActsTrk::HitCountsPerTrack::container &truth_particle_counts = track_association->at(track_i).countsPerTruthParticle();
180 tracksContainer->trackStateContainer().visitBackwards(
181 lastMeasurementIndex,
182 [this,
183 &n_measurements,
184 &measurement_to_truth_association_maps,
185 &truth_particle_counts,
186 &reco_hits,
187 &noise_hits,
188 &counted_truth_particles,
189 &compatible_assoc_container_counts
190 ](const typename ActsTrk::TrackStateBackend::ConstTrackStateProxy &state) -> void
191 {
192 if (!state.typeFlags().test(Acts::TrackStateFlag::OutlierFlag) && state.hasUncalibratedSourceLink()) {
193 auto sl = state.getUncalibratedSourceLink().template get<ATLASUncalibSourceLink>();
194 assert( sl != nullptr );
196
197 const ActsTrk::MeasurementToTruthParticleAssociation *association_map = measurement_to_truth_association_maps.at(to_underlying(uncalibMeas.type()));
198 if (association_map) {
199 if (!association_map->isCompatibleWith(dynamic_cast< const xAOD::UncalibratedMeasurementContainer *>(uncalibMeas.container()))) {
200 if (compatible_assoc_container_counts.second==0) {
201 ATH_MSG_ERROR("MeasurementToTruthParticleAssociation for measurement type " << to_underlying(uncalibMeas.type())
202 << " is not compatible with the measurement on track.");
203 }
204 ++compatible_assoc_container_counts.second;
205 return;
206 }
207 else {
208 ++compatible_assoc_container_counts.first;
209 }
210 ++n_measurements;
211 counted_truth_particles.clear();
212 for (const xAOD::TruthParticle *truth_particle : association_map->at(uncalibMeas.index()) ) {
213 const xAOD::TruthParticle *mother_particle = m_elasticDecayUtil.getMother(*truth_particle, m_maxEnergyLoss.value());
214
215 // do not count hits of associated truth particles again if they are associated to the same elastic decay chain:
216 if (std::find(counted_truth_particles.begin(), counted_truth_particles.end(), mother_particle->index())
217 ==counted_truth_particles.end()) {
218 counted_truth_particles.push_back(mother_particle->index());
219
220 ActsTrk::HitCountsPerTrack::container::iterator
221 hit_count_iter = std::find_if(truth_particle_counts.begin(),
222 truth_particle_counts.end(),
223 [mother_particle](const std::pair<const xAOD::TruthParticle *, HitCounterArray > &a) {
224 return a.first == mother_particle;
225 });
226 if (hit_count_iter == truth_particle_counts.end()) {
227 truth_particle_counts.push_back( std::make_pair(mother_particle, HitCounterArray{}));
228 hit_count_iter = truth_particle_counts.end()-1;
229 }
230 ++(hit_count_iter->second.at( to_underlying(uncalibMeas.type())));
231 }
232 }
233 if (association_map->at(uncalibMeas.index()).empty()) {
234 ++noise_hits.at( to_underlying(uncalibMeas.type()));
235 }
236 }
237 ++reco_hits.at( to_underlying(uncalibMeas.type()));
238 }
239
240 });
241 std::sort( truth_particle_counts.begin(),
242 truth_particle_counts.end(),
243 [](const std::pair<const xAOD::TruthParticle *, HitCounterArray > &a,
244 const std::pair<const xAOD::TruthParticle *, HitCounterArray > &b) {
245 return std::accumulate(a.second.begin(),a.second.end(),0u) > std::accumulate(b.second.begin(),b.second.end(),0u);
246 });
247 m_associationCounter.fillStatistics(n_measurements, truth_particle_counts.size());
248 ++(tracks_with_associated_truth[std::min(truth_particle_counts.size(),tracks_with_associated_truth.size()-1u)]);
249 ++track_i;
250 }
251 unsigned int idx=0;
252 for (unsigned int elm : tracks_with_associated_truth) {
253 m_nTracksWithAssociatedTruth[idx] += elm;
254 ++idx;
255 }
256 m_nIncompatibleMeasurementContainer += compatible_assoc_container_counts.second;
257 m_nCcompatibleMeasurementContainer += compatible_assoc_container_counts.first;
258
260 if (associationOutHandle.record( std::move(track_association)).isFailure()) {
261 ATH_MSG_ERROR("Failed to record track to truth assocition with key " << m_trackToTruthOut.key() );
262 return StatusCode::FAILURE;
263 }
264 return StatusCode::SUCCESS;
265 }
266
267} // 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)
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
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.
const SG::AuxVectorData * container() const
Return the container holding this element.
size_t index() const
Return the index of this element within its container.
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.
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
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130
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...
const xAOD::UncalibratedMeasurement & getUncalibratedMeasurement(const ATLASUncalibSourceLink &source_link)
std::underlying_type_t< T > to_underlying(T val)
MsgStream & operator<<(MsgStream &out, const ActsUtils::Stat &stat)
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.
UncalibratedMeasurement_v1 UncalibratedMeasurement
Define the version of the uncalibrated measurement class.
void fillStatistics(unsigned int n_measurements, unsigned int n_particles) const