2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
5#include "src/detail/AtlasUncalibSourceLinkAccessor.h"
6#include "ActsCalibrators/xAODUncalibMeasCalibrator.h"
9namespace ActsTrk::detail {
11template <Acts::TrackContainerFrontend track_container_t>
12inline 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);
21template <Acts::TrackContainerFrontend track_container_t>
22inline 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.
42template <Acts::TrackContainerFrontend track_container_t, typename IndexFun>
43inline 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().hasMeasurement())
62 if (!state.hasUncalibratedSourceLink())
65 if (removeSharedHits and !state.typeFlags().isSharedHit())
68 auto hit = detail::xAODUncalibMeasCalibrator::unpack(state.getUncalibratedSourceLink());
72 std::size_t hitIndex = indexFun(*hit);
73 if (!(hitIndex < m_firstTrackStateOnTheHit.size())) {
74 state.typeFlags().setIsSharedHit(false);
75 // Save ATH_MSG_ERROR() for the caller, since for simplicity and efficiency this class doesn't have access to AthMsgStream.
76 //std::cout << "ERROR hit index " << hitIndex << " past end of " << m_firstTrackStateOnTheHit.size() << " hit indices\n";
77 ++nBadTrackMeasurements;
81 // Check if hit not already used
82 if (m_firstTrackStateOnTheHit[hitIndex].trackIndex == s_noTrackState.trackIndex) {
83 state.typeFlags().setIsSharedHit(false);
84 m_firstTrackStateOnTheHit[hitIndex] = {track.index(), state.index()};
88 // if already used, control if first track state has been marked as shared
89 const TrackStateIndex& indexFirstTrackState = m_firstTrackStateOnTheHit[hitIndex];
90 if (!(indexFirstTrackState.trackIndex < tracks.size())) {
91 state.typeFlags().setIsSharedHit(false);
92 //std::cout << "ERROR track index " << indexFirstTrackState.trackIndex << " past end of " << tracks.size() << " tracks in container\n";
93 ++nBadTrackMeasurements;
97 auto firstTrack = tracks.getTrack(indexFirstTrackState.trackIndex);
98 auto& firstStateContainer = firstTrack.container().trackStateContainer();
100 if (!(indexFirstTrackState.stateIndex < firstStateContainer.size())) {
101 state.typeFlags().setIsSharedHit(false);
102 //std::cout << "ERROR track state index " << indexFirstTrackState.stateIndex << " past end of " << firstStateContainer.size() << " track states in container\n";
103 ++nBadTrackMeasurements;
107 auto firstState = firstStateContainer.getTrackState(indexFirstTrackState.stateIndex);
109 // if removeSharedHits is false, this is the nominal behaviour
110 if (!removeSharedHits) {
111 if (!firstState.typeFlags().isSharedHit()) {
112 firstState.typeFlags().setIsSharedHit();
113 firstTrack.nSharedHits()++;
116 // Decorate this track state
117 state.typeFlags().setIsSharedHit();
118 track.nSharedHits()++;
121 } else { // remove shared hits mode
122 if (firstState.typeFlags().isSharedHit()) {
123 firstState.typeFlags().setIsSharedHit(false);
125 //We should not find more shared measurements than initially attached to the track
126 if (firstTrack.nSharedHits() == 0) {
127 //std::cout << "ERROR inconsistency in removing shared hits for firstTrack " <<std::endl;
128 ++nBadTrackMeasurements;
131 firstTrack.nSharedHits()--;
135 // reset the flag for this track state
136 state.typeFlags().setIsSharedHit(false);
137 track.nSharedHits()--;
140 // clear up the firstTrackStateOnTheHit vector from the update
141 if (m_firstTrackStateOnTheHit[hitIndex].trackIndex == track.index() && m_firstTrackStateOnTheHit[hitIndex].stateIndex == state.index())
142 m_firstTrackStateOnTheHit[hitIndex] = s_noTrackState;
145 } // loop on the track states
147 return {nShared, nBadTrackMeasurements};
150} // namespace ActsTrk::detail