From 318837bd3661f533ae97ba19faa39da17bf3528e Mon Sep 17 00:00:00 2001 From: fchinu Date: Sun, 17 May 2026 21:15:55 +0200 Subject: [PATCH 1/3] ITS: add selections on tracks sharing clusters --- .../ITS/include/DataFormatsITS/TrackITS.h | 6 +++ .../include/ITStracking/Configuration.h | 5 ++ .../include/ITStracking/TrackerTraits.h | 2 + .../include/ITStracking/TrackingConfigParam.h | 5 ++ .../ITSMFT/ITS/tracking/src/Configuration.cxx | 3 ++ .../ITSMFT/ITS/tracking/src/TrackerTraits.cxx | 51 +++++++++++++++---- 6 files changed, 61 insertions(+), 11 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h index a06395e76afff..7f656e873960b 100644 --- a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h +++ b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h @@ -194,6 +194,12 @@ class TrackITSExt : public TrackITS GPUhdi() const int& getClusterIndex(int lr) const { return mIndex[lr]; } + GPUh() const int& getFirstLayerClusterIndex() const + { + int firstLayer = getFirstClusterLayer(); + return getClusterIndex(firstLayer); + } + GPUhdi() void setExternalClusterIndex(int layer, int idx, bool newCluster = false) { if (newCluster) { diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h index c939f39532fdb..8426d5fb5e711 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h @@ -98,6 +98,11 @@ struct TrackingParameters { bool PrintMemory = false; // print allocator usage in epilog report size_t MaxMemory = std::numeric_limits::max(); bool DropTFUponFailure = false; + + // Selections on tracks sharing clusters + float SharedClusterMaxDeltaPhi = 0.05f; // For tracks sharing clusters, maximum allowed delta phi at the cluster position + float SharedClusterMaxDeltaEta = 0.03f; // For tracks sharing clusters, maximum allowed delta eta at the cluster position + bool SharedClusterOppositeSign = false; // For tracks sharing clusters, require opposite sign of the tracklets }; struct VertexingParameters { diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h index 647403bb6b548..0318461434ef6 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h @@ -58,6 +58,8 @@ class TrackerTraits void acceptTracks(int iteration, bounded_vector& tracks, bounded_vector>& firstClusters, bounded_vector>& sharedFirstClusters); void markTracks(int iteration, bounded_vector>& sharedFirstClusters); + bool areTracksSelected(int iteration, const TrackITSExt& t1, const TrackITSExt& t2); + void updateTrackingParameters(const std::vector& trkPars) { mTrkParams = trkPars; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h index 21b4f928d5b73..a2f37751ddd38 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h @@ -104,6 +104,11 @@ struct TrackerParamConfig : public o2::conf::ConfigurableParamHelper TrackingMode::getTrackingParameters(TrackingMode p.SaveTimeBenchmarks = tc.saveTimeBenchmarks; p.FataliseUponFailure = tc.fataliseUponFailure; p.AllowSharingFirstCluster = tc.allowSharingFirstCluster; + p.SharedClusterMaxDeltaPhi = tc.sharedClusterMaxDeltaPhi; + p.SharedClusterMaxDeltaEta = tc.sharedClusterMaxDeltaEta; + p.SharedClusterOppositeSign = tc.sharedClusterOppositeSign; const auto iter = &p - trackParams.data(); if (iter < constants::MaxIter) { p.MaxHoles = tc.maxHolesIter[iter]; diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx index 9fef067559e8a..e068e2d568502 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx @@ -876,23 +876,52 @@ void TrackerTraits::markTracks(int iteration, bounded_vectorgetTracks()) { - int firstLayer{mTrkParams[iteration].NLayers}, firstCluster{constants::UnusedIndex}; - for (int iLayer{0}; iLayer < mTrkParams[iteration].NLayers; ++iLayer) { - if (track.getClusterIndex(iLayer) == constants::UnusedIndex) { - continue; - } - firstLayer = iLayer; - firstCluster = track.getClusterIndex(iLayer); - break; - } + auto& tracks = mTimeFrame->getTracks(); + std::sort(tracks.begin(), tracks.end(), [](const auto& t1, const auto& t2) { + return t1.getFirstLayerClusterIndex() < t2.getFirstLayerClusterIndex(); + }); + + for (int i{0}; i < static_cast(tracks.size()); ++i) { + auto& track = tracks[i]; + int firstLayer{track.getFirstClusterLayer()}, firstCluster{track.getFirstLayerClusterIndex()}; if (std::binary_search(sharedFirstClusters[firstLayer].begin(), sharedFirstClusters[firstLayer].end(), firstCluster)) { - track.setSharedClusters(); + int j = i + 1; + while (j < static_cast(tracks.size()) && tracks[j].getFirstLayerClusterIndex() == firstCluster) { + auto& track2 = tracks[j]; + if (areTracksSelected(iteration, track, track2)) { + for (int iLayer{track.getFirstClusterLayer()}; iLayer < track.getFirstClusterLayer() + track.getNClusters(); ++iLayer) { + } + for (int iLayer{track2.getFirstClusterLayer()}; iLayer < track2.getFirstClusterLayer() + track2.getNClusters(); ++iLayer) { + } + track.setSharedClusters(); + track2.setSharedClusters(); + } + ++j; + } } } } } +template +bool TrackerTraits::areTracksSelected(int iteration, const TrackITSExt& t1, const TrackITSExt& t2) +{ + const auto t1FirstLayer{t1.getFirstClusterLayer()}, t2FirstLayer{t2.getFirstClusterLayer()}; + if (mTimeFrame->getClusterROF(t1FirstLayer, t1.getClusterIndex(t1FirstLayer)) != mTimeFrame->getClusterROF(t2FirstLayer, t2.getClusterIndex(t2FirstLayer))) { + return false; + } + if (o2::math_utils::detail::deltaPhiSmall(t1.getPhi(), t2.getPhi()) > mTrkParams[iteration].SharedClusterMaxDeltaPhi) { + return false; + } + if (std::abs(t1.getEta() - t2.getEta()) > mTrkParams[iteration].SharedClusterMaxDeltaEta) { + return false; + } + if (mTrkParams[iteration].SharedClusterOppositeSign && t1.getSign() == t2.getSign()) { + return false; + } + return true; +} + template void TrackerTraits::setBz(float bz) { From 09b57b4debc53fe79ce991e6fb3a781af036a3d8 Mon Sep 17 00:00:00 2001 From: fchinu Date: Mon, 18 May 2026 10:56:22 +0200 Subject: [PATCH 2/3] Refactor selection function, return simple int instead of reference to int --- .../ITS/include/DataFormatsITS/TrackITS.h | 4 +- .../include/ITStracking/Configuration.h | 2 +- .../include/ITStracking/TrackerTraits.h | 2 - .../include/ITStracking/TrackingConfigParam.h | 2 +- .../ITSMFT/ITS/tracking/src/TrackerTraits.cxx | 42 ++++++++----------- 5 files changed, 22 insertions(+), 30 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h index 7f656e873960b..89f6416c6e177 100644 --- a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h +++ b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h @@ -192,9 +192,9 @@ class TrackITSExt : public TrackITS getClusterRefs().setEntries(ncl); } - GPUhdi() const int& getClusterIndex(int lr) const { return mIndex[lr]; } + GPUhdi() const int getClusterIndex(int lr) const { return mIndex[lr]; } - GPUh() const int& getFirstLayerClusterIndex() const + GPUh() const int getFirstLayerClusterIndex() const { int firstLayer = getFirstClusterLayer(); return getClusterIndex(firstLayer); diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h index 8426d5fb5e711..852c5ecd24633 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h @@ -70,7 +70,6 @@ struct TrackingParameters { float DiamondCov[6] = {25.e-6f, 0.f, 0.f, 25.e-6f, 0.f, 36.f}; /// General parameters - bool AllowSharingFirstCluster = false; int ClusterSharing = 0; int MinTrackLength = 7; int MaxHoles = 0; @@ -100,6 +99,7 @@ struct TrackingParameters { bool DropTFUponFailure = false; // Selections on tracks sharing clusters + bool AllowSharingFirstCluster = false; float SharedClusterMaxDeltaPhi = 0.05f; // For tracks sharing clusters, maximum allowed delta phi at the cluster position float SharedClusterMaxDeltaEta = 0.03f; // For tracks sharing clusters, maximum allowed delta eta at the cluster position bool SharedClusterOppositeSign = false; // For tracks sharing clusters, require opposite sign of the tracklets diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h index 0318461434ef6..647403bb6b548 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h @@ -58,8 +58,6 @@ class TrackerTraits void acceptTracks(int iteration, bounded_vector& tracks, bounded_vector>& firstClusters, bounded_vector>& sharedFirstClusters); void markTracks(int iteration, bounded_vector>& sharedFirstClusters); - bool areTracksSelected(int iteration, const TrackITSExt& t1, const TrackITSExt& t2); - void updateTrackingParameters(const std::vector& trkPars) { mTrkParams = trkPars; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h index a2f37751ddd38..69aa3c5fdaf06 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h @@ -102,9 +102,9 @@ struct TrackerParamConfig : public o2::conf::ConfigurableParamHelper::max(); bool dropTFUponFailure = false; bool fataliseUponFailure = true; // granular management of the fatalisation in async mode - bool allowSharingFirstCluster = false; // allow first cluster sharing among tracks // Selections on tracks sharing clusters + bool allowSharingFirstCluster = false; // allow first cluster sharing among tracks float sharedClusterMaxDeltaPhi = 0.05f; // Maximum allowed delta phi at the cluster position float sharedClusterMaxDeltaEta = 0.03f; // Maximum allowed delta eta at the cluster position bool sharedClusterOppositeSign = false; // Require opposite sign of the tracklets diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx index e068e2d568502..e0aacd9399529 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx @@ -881,6 +881,23 @@ void TrackerTraits::markTracks(int iteration, bounded_vectorgetClusterROF(t1FirstLayer, t1.getClusterIndex(t1FirstLayer)) != mTimeFrame->getClusterROF(t2FirstLayer, t2.getClusterIndex(t2FirstLayer))) { + return false; + } + if (o2::math_utils::detail::deltaPhiSmall(t1.getPhi(), t2.getPhi()) > mTrkParams[iteration].SharedClusterMaxDeltaPhi) { + return false; + } + if (std::abs(t1.getEta() - t2.getEta()) > mTrkParams[iteration].SharedClusterMaxDeltaEta) { + return false; + } + if (mTrkParams[iteration].SharedClusterOppositeSign && t1.getSign() == t2.getSign()) { + return false; + } + return true; + }; + for (int i{0}; i < static_cast(tracks.size()); ++i) { auto& track = tracks[i]; int firstLayer{track.getFirstClusterLayer()}, firstCluster{track.getFirstLayerClusterIndex()}; @@ -888,11 +905,7 @@ void TrackerTraits::markTracks(int iteration, bounded_vector(tracks.size()) && tracks[j].getFirstLayerClusterIndex() == firstCluster) { auto& track2 = tracks[j]; - if (areTracksSelected(iteration, track, track2)) { - for (int iLayer{track.getFirstClusterLayer()}; iLayer < track.getFirstClusterLayer() + track.getNClusters(); ++iLayer) { - } - for (int iLayer{track2.getFirstClusterLayer()}; iLayer < track2.getFirstClusterLayer() + track2.getNClusters(); ++iLayer) { - } + if (areTracksSelected(track, track2)) { track.setSharedClusters(); track2.setSharedClusters(); } @@ -903,25 +916,6 @@ void TrackerTraits::markTracks(int iteration, bounded_vector -bool TrackerTraits::areTracksSelected(int iteration, const TrackITSExt& t1, const TrackITSExt& t2) -{ - const auto t1FirstLayer{t1.getFirstClusterLayer()}, t2FirstLayer{t2.getFirstClusterLayer()}; - if (mTimeFrame->getClusterROF(t1FirstLayer, t1.getClusterIndex(t1FirstLayer)) != mTimeFrame->getClusterROF(t2FirstLayer, t2.getClusterIndex(t2FirstLayer))) { - return false; - } - if (o2::math_utils::detail::deltaPhiSmall(t1.getPhi(), t2.getPhi()) > mTrkParams[iteration].SharedClusterMaxDeltaPhi) { - return false; - } - if (std::abs(t1.getEta() - t2.getEta()) > mTrkParams[iteration].SharedClusterMaxDeltaEta) { - return false; - } - if (mTrkParams[iteration].SharedClusterOppositeSign && t1.getSign() == t2.getSign()) { - return false; - } - return true; -} - template void TrackerTraits::setBz(float bz) { From b9a667e34a79ab437977bf5ec036d2a6ddcec869 Mon Sep 17 00:00:00 2001 From: fchinu Date: Mon, 18 May 2026 11:15:46 +0200 Subject: [PATCH 3/3] Use isPhiDifferenceBelow, avoid variable narrowing --- Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx index e0aacd9399529..fcbf1ba8c781b 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx @@ -886,7 +886,7 @@ void TrackerTraits::markTracks(int iteration, bounded_vectorgetClusterROF(t1FirstLayer, t1.getClusterIndex(t1FirstLayer)) != mTimeFrame->getClusterROF(t2FirstLayer, t2.getClusterIndex(t2FirstLayer))) { return false; } - if (o2::math_utils::detail::deltaPhiSmall(t1.getPhi(), t2.getPhi()) > mTrkParams[iteration].SharedClusterMaxDeltaPhi) { + if (!math_utils::isPhiDifferenceBelow(t1.getPhi(), t2.getPhi(), mTrkParams[iteration].SharedClusterMaxDeltaPhi)) { return false; } if (std::abs(t1.getEta() - t2.getEta()) > mTrkParams[iteration].SharedClusterMaxDeltaEta) { @@ -900,7 +900,8 @@ void TrackerTraits::markTracks(int iteration, bounded_vector(tracks.size()); ++i) { auto& track = tracks[i]; - int firstLayer{track.getFirstClusterLayer()}, firstCluster{track.getFirstLayerClusterIndex()}; + uint32_t firstLayer{track.getFirstClusterLayer()}; + int firstCluster{track.getFirstLayerClusterIndex()}; if (std::binary_search(sharedFirstClusters[firstLayer].begin(), sharedFirstClusters[firstLayer].end(), firstCluster)) { int j = i + 1; while (j < static_cast(tracks.size()) && tracks[j].getFirstLayerClusterIndex() == firstCluster) {