ATLAS Offline Software
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 namespace {
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 }
22 namespace ActsTrk
23 {
24  // to dump
25  inline MsgStream &operator<<(MsgStream &out, const ActsUtils::Stat &stat) {
27  return out;
28  }
29 
31  ISvcLocator *pSvcLocator)
32  : AthReentrantAlgorithm(name, pSvcLocator)
33  {
34  }
35 
37  {
38  ATH_CHECK( m_trackingGeometryTool.retrieve() );
40  ATH_CHECK( m_pixelClustersToTruth.initialize() );
41  ATH_CHECK( m_stripClustersToTruth.initialize() );
42 
43  ATH_CHECK( m_trackToTruthOut.initialize() );
44 
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  }
103  msg() << std::endl;
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  }
127  if (!tracksContainer.isValid()) {
128  ATH_MSG_ERROR("No tracks for key " << m_tracksContainerKey.key() );
129  return StatusCode::FAILURE;
130  }
131  track_association->resize( tracksContainer->size() );
132  track_association->setSourceContainer(DataLink<ActsTrk::TrackContainer>(*tracksContainer,ctx));
133  Acts::GeometryContext tgContext = m_trackingGeometryTool->getGeometryContext(ctx).context();
134 
137  measurement_to_truth_association_maps{};
138  measurement_to_truth_association_maps[to_underlying(xAOD::UncalibMeasType::PixelClusterType)]=pixelClustersToTruthAssociation.cptr();
139  measurement_to_truth_association_maps[to_underlying(xAOD::UncalibMeasType::StripClusterType)]=stripClustersToTruthAssociation.cptr();
140  ATH_MSG_DEBUG("Measurement association entries: " << measurement_to_truth_association_maps[to_underlying(xAOD::UncalibMeasType::PixelClusterType)]->size()
141  << " + " << measurement_to_truth_association_maps[to_underlying(xAOD::UncalibMeasType::StripClusterType)]->size()
142  );
143  unsigned int track_i=0;
144  std::array<unsigned int,s_NCounterForAssociatedTruth> tracks_with_associated_truth{};
145  std::pair<unsigned int, unsigned int> compatible_assoc_container_counts{};
147  // used to suppress reoccurring error messages
149  ++compatible_assoc_container_counts.second;
150  }
151 
152  std::vector<unsigned int> counted_truth_particles;
153  counted_truth_particles.reserve(10);
154  --track_i; // to have track_i at the begining of the loop
155  for (const typename ActsTrk::TrackContainer::ConstTrackProxy track : *tracksContainer) {
156  ++track_i;
157  const auto lastMeasurementIndex = track.tipIndex();
158 
159  unsigned int n_measurements=0u;
160 
161  HitCounterArray &reco_hits = track_association->at(track_i).totalCounts();
162  HitCounterArray &noise_hits = track_association->at(track_i).noiseCounts();
163  ActsTrk::HitCountsPerTrack::container &truth_particle_counts = track_association->at(track_i).countsPerTruthParticle();
164  tracksContainer->trackStateContainer().visitBackwards(
165  lastMeasurementIndex,
166  [this,
167  &n_measurements,
168  &measurement_to_truth_association_maps,
169  &truth_particle_counts,
170  &reco_hits,
171  &noise_hits,
172  &counted_truth_particles,
173  &compatible_assoc_container_counts
174  ](const typename ActsTrk::TrackStateBackend::ConstTrackStateProxy &state) -> void
175  {
176  if (!state.typeFlags().test(Acts::TrackStateFlag::OutlierFlag) && state.hasUncalibratedSourceLink()) {
177  auto sl = state.getUncalibratedSourceLink().template get<ATLASUncalibSourceLink>();
178  assert( sl != nullptr );
179  const xAOD::UncalibratedMeasurement &uncalibMeas = getUncalibratedMeasurement(sl);
180 
181 
182  const ActsTrk::MeasurementToTruthParticleAssociation *association_map = measurement_to_truth_association_maps.at(to_underlying(uncalibMeas.type()));
183  if (association_map) {
184  if (!association_map->isCompatibleWith(dynamic_cast< const xAOD::UncalibratedMeasurementContainer *>(uncalibMeas.container()))) {
185  if (compatible_assoc_container_counts.second==0) {
186  ATH_MSG_ERROR("MeasurementToTruthParticleAssociation for measurement type " << to_underlying(uncalibMeas.type())
187  << " is not compatible with the measurement on track.");
188  }
189  ++compatible_assoc_container_counts.second;
190  return;
191  }
192  else {
193  ++compatible_assoc_container_counts.first;
194  }
195  ++n_measurements;
196  counted_truth_particles.clear();
197  for (const xAOD::TruthParticle *truth_particle : association_map->at(uncalibMeas.index()) ) {
198  const xAOD::TruthParticle *mother_particle = m_elasticDecayUtil.getMother(*truth_particle, m_maxEnergyLoss.value());
199 
200  // do not count hits of associated truth particles again if they are associated to the same elastic decay chain:
201  if (std::find(counted_truth_particles.begin(), counted_truth_particles.end(), mother_particle->index())
202  ==counted_truth_particles.end()) {
203  counted_truth_particles.push_back(mother_particle->index());
204 
205  ActsTrk::HitCountsPerTrack::container::iterator
206  hit_count_iter = std::find_if(truth_particle_counts.begin(),
207  truth_particle_counts.end(),
208  [mother_particle](const std::pair<const xAOD::TruthParticle *, HitCounterArray > &a) {
209  return a.first == mother_particle;
210  });
211  if (hit_count_iter == truth_particle_counts.end()) {
212  truth_particle_counts.push_back( std::make_pair(mother_particle, HitCounterArray{}));
213  hit_count_iter = truth_particle_counts.end()-1;
214  }
215  ++(hit_count_iter->second.at( to_underlying(uncalibMeas.type())));
216  }
217  }
218  if (association_map->at(uncalibMeas.index()).empty()) {
219  ++noise_hits.at( to_underlying(uncalibMeas.type()));
220  }
221  }
222  ++reco_hits.at( to_underlying(uncalibMeas.type()));
223  }
224 
225  });
226  std::sort( truth_particle_counts.begin(),
227  truth_particle_counts.end(),
228  [](const std::pair<const xAOD::TruthParticle *, HitCounterArray > &a,
229  const std::pair<const xAOD::TruthParticle *, HitCounterArray > &b) {
230  return std::accumulate(a.second.begin(),a.second.end(),0u) > std::accumulate(b.second.begin(),b.second.end(),0u);
231  });
232  m_associationCounter.fillStatistics(n_measurements, truth_particle_counts.size());
233  ++(tracks_with_associated_truth[std::min(truth_particle_counts.size(),tracks_with_associated_truth.size()-1u)]);
234  }
235  unsigned int idx=0;
236  for (unsigned int elm : tracks_with_associated_truth) {
237  m_nTracksWithAssociatedTruth[idx] += elm;
238  ++idx;
239  }
240  m_nIncompatibleMeasurementContainer += compatible_assoc_container_counts.second;
241  m_nCcompatibleMeasurementContainer += compatible_assoc_container_counts.first;
242 
243  SG::WriteHandle<TrackToTruthParticleAssociation> associationOutHandle(m_trackToTruthOut, ctx);
244  if (associationOutHandle.record( std::move(track_association)).isFailure()) {
245  ATH_MSG_ERROR("Failed to record track to truth assocition with key " << m_trackToTruthOut.key() );
246  return StatusCode::FAILURE;
247  }
248  return StatusCode::SUCCESS;
249  }
250 
251 } // namespace
ActsTrk::TrackToTruthAssociationAlg::finalize
virtual StatusCode finalize() override
Definition: TrackToTruthAssociationAlg.cxx:76
ActsTrk::TrackToTruthAssociationAlg::TrackToTruthAssociationAlg
TrackToTruthAssociationAlg(const std::string &name, ISvcLocator *pSvcLocator)
Definition: TrackToTruthAssociationAlg.cxx:30
ActsTrk::TrackToTruthAssociationAlg::initialize
virtual StatusCode initialize() override
Definition: TrackToTruthAssociationAlg.cxx:36
createSimpleDistributions.IsDebug
bool IsDebug
Definition: createSimpleDistributions.py:12
header
Definition: hcg.cxx:526
SG::ReadHandle::cptr
const_pointer_type cptr()
Dereference the pointer.
tail
std::string tail(std::string s, const std::string &pattern)
tail of a string
Definition: computils.cxx:300
ActsTrk::TrackToTruthAssociationAlg::m_associationCounter
AssociationCounter< TrackToTruthParticleAssociationDebugHists > m_associationCounter
Definition: TrackToTruthAssociationAlg.h:99
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
xAOD::UncalibMeasType::StripClusterType
@ StripClusterType
PlotCalibFromCool.label
label
Definition: PlotCalibFromCool.py:78
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
AthCommonMsg< Gaudi::Algorithm >::msgLvl
bool msgLvl(const MSG::Level lvl) const
Definition: AthCommonMsg.h:30
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
ActsTrk::MeasurementToTruthParticleAssociation
Definition: MeasurementToTruthParticleAssociation.h:18
ActsTrk::to_underlying
constexpr std::underlying_type< T_EnumClass >::type to_underlying(T_EnumClass an_enum)
Helper to convert class enum into an integer.
Definition: HitSummaryDataUtils.h:24
Trk::u
@ u
Enums for curvilinear frames.
Definition: ParamDefs.h:83
ElasticDecayUtil::dumpStatistics
void dumpStatistics(T_OutStream &out) const
ActsTrk::TrackToTruthAssociationAlg::AssociationCounter::fillStatistics
void fillStatistics(unsigned int n_measurements, unsigned int n_particles) const
Definition: TrackToTruthAssociationAlg.cxx:60
AthReentrantAlgorithm
An algorithm that can be simultaneously executed in multiple threads.
Definition: AthReentrantAlgorithm.h:83
ActsTrk::HitCounterArray
Definition: TrackToTruthParticleAssociation.h:25
SG::makeHandle
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition: ReadCondHandle.h:269
ActsUtils::Stat
Simple class to gather statistics : min, max, mean, rms.
Definition: StatUtils.h:16
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
ActsTrk::HitCountsPerTrack::container
boost::container::small_vector< std::pair< const xAOD::TruthParticle *, HitCounterArray >, NTruthParticlesPerTrack > container
Definition: TrackToTruthParticleAssociation.h:39
ActsTrk::TrackToTruthAssociationAlg::execute
virtual StatusCode execute(const EventContext &ctx) const override
Definition: TrackToTruthAssociationAlg.cxx:111
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
ActsUtils::dumpStat
void dumpStat(T_Stream &out, const Stat &stat)
Dump the given statistics object to the given output stream.
Definition: StatUtils.h:62
lumiFormat.i
int i
Definition: lumiFormat.py:92
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
TrackToTruthAssociationAlg.h
ActsTrk::TrackToTruthAssociationAlg::m_elasticDecayUtil
ElasticDecayUtil< TrackToTruthParticleAssociationDebugHists > m_elasticDecayUtil
Definition: TrackToTruthAssociationAlg.h:72
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
ActsTrk::operator<<
MsgStream & operator<<(MsgStream &out, const ActsUtils::Stat &stat)
Definition: TrackToTruthAssociationAlg.cxx:25
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
beamspotman.stat
stat
Definition: beamspotman.py:266
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
ActsTrk::TrackToTruthAssociationAlg::m_stripClustersToTruth
SG::ReadHandleKey< MeasurementToTruthParticleAssociation > m_stripClustersToTruth
Definition: TrackToTruthAssociationAlg.h:64
min
#define min(a, b)
Definition: cfImp.cxx:40
TruthVertex.h
lumiFormat.array
array
Definition: lumiFormat.py:98
xAOD::UncalibMeasType::nTypes
@ nTypes
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
ActsTrk::TrackToTruthAssociationAlg::m_energyLossBinning
std::conditional< TrackToTruthParticleAssociationDebugHists, Gaudi::Property< std::vector< float > >, EmptyProperty >::type m_energyLossBinning
Definition: TrackToTruthAssociationAlg.h:77
ActsTrk::TrackToTruthAssociationAlg::m_nCcompatibleMeasurementContainer
std::atomic< std::size_t > m_nCcompatibleMeasurementContainer
Definition: TrackToTruthAssociationAlg.h:103
ActsTrk::TrackToTruthParticleAssociationDebugHists
constexpr bool TrackToTruthParticleAssociationDebugHists
Definition: TrackToTruthAssociationAlg.h:42
python.Dumpers.typename
def typename(t)
Definition: Dumpers.py:194
ActsTrk::TrackToTruthAssociationAlg::m_trackingGeometryTool
ToolHandle< IActsTrackingGeometryTool > m_trackingGeometryTool
Definition: TrackToTruthAssociationAlg.h:56
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:76
ActsTrk::TrackToTruthAssociationAlg::m_pixelClustersToTruth
SG::ReadHandleKey< MeasurementToTruthParticleAssociation > m_pixelClustersToTruth
Definition: TrackToTruthAssociationAlg.h:62
a
TList * a
Definition: liststreamerinfos.cxx:10
ActsTrk::TrackToTruthAssociationAlg::m_nIncompatibleMeasurementContainer
std::atomic< std::size_t > m_nIncompatibleMeasurementContainer
Definition: TrackToTruthAssociationAlg.h:102
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
AthCommonMsg< Gaudi::Algorithm >::msg
MsgStream & msg() const
Definition: AthCommonMsg.h:24
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
ActsTrk::TrackToTruthAssociationAlg::m_tracksContainerKey
SG::ReadHandleKey< ActsTrk::TrackContainer > m_tracksContainerKey
Definition: TrackToTruthAssociationAlg.h:59
ActsTrk::TrackToTruthAssociationAlg::AssociationCounter::dumpStatistics
void dumpStatistics(T_OutStream &out) const
Definition: TrackToTruthAssociationAlg.cxx:51
ActsTrk
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
Definition: MuonDetectorBuilderTool.cxx:34
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
TruthParticle.h
ElasticDecayUtil::setEnergyLossBinning
void setEnergyLossBinning(const typename std::conditional< IsDebug, std::vector< float >, EmptyProperty >::type &binning)
xAOD::UncalibMeasType::PixelClusterType
@ PixelClusterType
ActsTrk::TrackToTruthAssociationAlg::m_trackToTruthOut
SG::WriteHandleKey< TrackToTruthParticleAssociation > m_trackToTruthOut
Definition: TrackToTruthAssociationAlg.h:67