ATLAS Offline Software
SharedHitCounter.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "src/detail/AtlasUncalibSourceLinkAccessor.h"
6 
7 #include <algorithm>
8 
9 namespace ActsTrk::detail {
10 
11 template <Acts::TrackContainerFrontend track_container_t>
12 inline auto SharedHitCounter::computeSharedHits(typename track_container_t::TrackProxy &track,
13  track_container_t &tracks,
14  const MeasurementIndex &measurementIndex,
15  bool removeSharedHits) -> ReturnSharedAndBad {
16  return computeSharedHits(track, tracks, measurementIndex.size(), [&measurementIndex](const xAOD::UncalibratedMeasurement &hit) -> std::size_t {
17  return measurementIndex.index(hit);
18  }, removeSharedHits);
19 }
20 
21 template <Acts::TrackContainerFrontend track_container_t>
22 inline auto SharedHitCounter::computeSharedHitsDynamic(typename track_container_t::TrackProxy &track,
23  track_container_t &tracks,
24  MeasurementIndex &measurementIndex,
25  bool removeSharedHits) -> ReturnSharedAndBad {
26  return computeSharedHits(track, tracks, measurementIndex.size(), [this, &measurementIndex](const xAOD::UncalibratedMeasurement &hit) -> std::size_t {
27  auto [index, newContainer] = measurementIndex.newMeasurementIndex(hit);
28  if (newContainer)
29  m_firstTrackStateOnTheHit.resize(measurementIndex.size(), s_noTrackState);
30  return index;
31  },removeSharedHits);
32 }
33 
34 
35  /**
36  track : the track under investigation and that will be updated with the shared hit information
37  tracks : the track container. Used to check what hits are used. Both tracks that share hits will get the shared states set and nShared hits updated
38  indexSize : the size of measurements to be used fo shared hit counting
39  indexFun : template param to get the index from the hit
40  removeSharedHits : if true this function will remove the shared hits from the track and the matching tracks and reset the states sharedHit flag.
41  */
42 template <Acts::TrackContainerFrontend track_container_t, typename IndexFun>
43 inline auto SharedHitCounter::computeSharedHits(typename track_container_t::TrackProxy &track,
44  track_container_t &tracks,
45  std::size_t indexSize,
46  IndexFun &&indexFun,
47  bool removeSharedHits) -> ReturnSharedAndBad {
48  // Based on ActsExamples::TrackFindingAlgorithm::computeSharedHits().
49  // Finds shared hits in the reconstructed track and updates SharedHitFlag in both tracks.
50  // Uses measurementIndex to convert hit to hitIndex, and then m_firstTrackStateOnTheHit[] to convert hitIndex -> TrackStateIndex
51  // Returns stats: nShared and nBadTrackMeasurements
52 
53  if (m_firstTrackStateOnTheHit.size() < indexSize)
54  m_firstTrackStateOnTheHit.resize(indexSize, s_noTrackState);
55 
56  std::size_t nShared = 0;
57  std::size_t nBadTrackMeasurements = 0;
58  for (auto state : track.trackStatesReversed()) {
59  if (!state.typeFlags().test(Acts::TrackStateFlag::MeasurementFlag))
60  continue;
61 
62  if (!state.hasUncalibratedSourceLink())
63  continue;
64 
65  if (removeSharedHits and !state.typeFlags().test(Acts::TrackStateFlag::SharedHitFlag))
66  continue;
67 
68  auto sl = state.getUncalibratedSourceLink().template get<ATLASUncalibSourceLink>();
69  const xAOD::UncalibratedMeasurement& hit = getUncalibratedMeasurement(sl);
70  std::size_t hitIndex = indexFun(hit);
71  if (!(hitIndex < m_firstTrackStateOnTheHit.size())) {
72  state.typeFlags().reset(Acts::TrackStateFlag::SharedHitFlag);
73  // Save ATH_MSG_ERROR() for the caller, since for simplicity and efficiency this class doesn't have access to AthMsgStream.
74  //std::cout << "ERROR hit index " << hitIndex << " past end of " << m_firstTrackStateOnTheHit.size() << " hit indices\n";
75  ++nBadTrackMeasurements;
76  continue;
77  }
78 
79  // Check if hit not already used
80  if (m_firstTrackStateOnTheHit[hitIndex].trackIndex == s_noTrackState.trackIndex) {
81  state.typeFlags().reset(Acts::TrackStateFlag::SharedHitFlag);
82  m_firstTrackStateOnTheHit[hitIndex] = {track.index(), state.index()};
83  continue;
84  }
85 
86  // if already used, control if first track state has been marked as shared
87  const TrackStateIndex& indexFirstTrackState = m_firstTrackStateOnTheHit[hitIndex];
88  if (!(indexFirstTrackState.trackIndex < tracks.size())) {
89  state.typeFlags().reset(Acts::TrackStateFlag::SharedHitFlag);
90  //std::cout << "ERROR track index " << indexFirstTrackState.trackIndex << " past end of " << tracks.size() << " tracks in container\n";
91  ++nBadTrackMeasurements;
92  continue;
93  }
94 
95  auto firstTrack = tracks.getTrack(indexFirstTrackState.trackIndex);
96  auto& firstStateContainer = firstTrack.container().trackStateContainer();
97 
98  if (!(indexFirstTrackState.stateIndex < firstStateContainer.size())) {
99  state.typeFlags().reset(Acts::TrackStateFlag::SharedHitFlag);
100  //std::cout << "ERROR track state index " << indexFirstTrackState.stateIndex << " past end of " << firstStateContainer.size() << " track states in container\n";
101  ++nBadTrackMeasurements;
102  continue;
103  }
104 
105  auto firstState = firstStateContainer.getTrackState(indexFirstTrackState.stateIndex);
106 
107  // if removeSharedHits is false, this is the nominal behaviour
108  if (!removeSharedHits) {
109  if (!firstState.typeFlags().test(Acts::TrackStateFlag::SharedHitFlag)) {
110  firstState.typeFlags().set(Acts::TrackStateFlag::SharedHitFlag);
111  firstTrack.nSharedHits()++;
112  ++nShared;
113  }
114  // Decorate this track state
115  state.typeFlags().set(Acts::TrackStateFlag::SharedHitFlag);
116  track.nSharedHits()++;
117  ++nShared;
118 
119  } else { // remove shared hits mode
120  if (firstState.typeFlags().test(Acts::TrackStateFlag::SharedHitFlag)) {
121  firstState.typeFlags().reset(Acts::TrackStateFlag::SharedHitFlag);
122 
123  //We should not find more shared measurements than initially attached to the track
124  if (firstTrack.nSharedHits() == 0) {
125  //std::cout << "ERROR inconsistency in removing shared hits for firstTrack " <<std::endl;
126  ++nBadTrackMeasurements;
127  }
128  else {
129  firstTrack.nSharedHits()--;
130  ++nShared;
131  }
132  }
133  // reset the flag for this track state
134  state.typeFlags().reset(Acts::TrackStateFlag::SharedHitFlag);
135  track.nSharedHits()--;
136  ++nShared;
137 
138  // clear up the firstTrackStateOnTheHit vector from the update
139  if (m_firstTrackStateOnTheHit[hitIndex].trackIndex == track.index() && m_firstTrackStateOnTheHit[hitIndex].stateIndex == state.index())
140  m_firstTrackStateOnTheHit[hitIndex] = s_noTrackState;
141  }
142 
143  } // loop on the track states
144 
145  return {nShared, nBadTrackMeasurements};
146 }
147 
148 } // namespace ActsTrk::detail