2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
5 #include "src/detail/AtlasUncalibSourceLinkAccessor.h"
9 namespace ActsTrk::detail {
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);
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);
29 m_firstTrackStateOnTheHit.resize(measurementIndex.size(), s_noTrackState);
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.
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,
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
53 if (m_firstTrackStateOnTheHit.size() < indexSize)
54 m_firstTrackStateOnTheHit.resize(indexSize, s_noTrackState);
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))
62 if (!state.hasUncalibratedSourceLink())
65 if (removeSharedHits and !state.typeFlags().test(Acts::TrackStateFlag::SharedHitFlag))
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;
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()};
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;
95 auto firstTrack = tracks.getTrack(indexFirstTrackState.trackIndex);
96 auto& firstStateContainer = firstTrack.container().trackStateContainer();
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;
105 auto firstState = firstStateContainer.getTrackState(indexFirstTrackState.stateIndex);
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()++;
114 // Decorate this track state
115 state.typeFlags().set(Acts::TrackStateFlag::SharedHitFlag);
116 track.nSharedHits()++;
119 } else { // remove shared hits mode
120 if (firstState.typeFlags().test(Acts::TrackStateFlag::SharedHitFlag)) {
121 firstState.typeFlags().reset(Acts::TrackStateFlag::SharedHitFlag);
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;
129 firstTrack.nSharedHits()--;
133 // reset the flag for this track state
134 state.typeFlags().reset(Acts::TrackStateFlag::SharedHitFlag);
135 track.nSharedHits()--;
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;
143 } // loop on the track states
145 return {nShared, nBadTrackMeasurements};
148 } // namespace ActsTrk::detail