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