Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: Updating the cuts in ScoreBased Solver to eta based cuts. #4054

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
bf49b8f
temp fix
Ragansu Oct 17, 2024
64f2457
Merge branch 'main' of github.com:Ragansu/acts into main
Ragansu Jan 15, 2025
a0c9dc2
Merge branch 'main' of github.com:Ragansu/acts into main
Ragansu Jan 22, 2025
1ec76b1
added eta based cuts
Ragansu Jan 22, 2025
c8ae9f9
removed cout statements
Ragansu Jan 22, 2025
bd5ddc3
Update ScoreBasedAmbiguityResolution.ipp
Ragansu Jan 23, 2025
81cfacf
updated Exams and tests
Ragansu Jan 23, 2025
284a2da
fixed formating
Ragansu Jan 23, 2025
357ceae
format check for hpp
Ragansu Jan 23, 2025
1f6dc5c
updated Examply python code
Ragansu Jan 23, 2025
926c57b
update python scripts
Ragansu Jan 23, 2025
96de71d
fixed json reader
Ragansu Jan 23, 2025
54cd923
fixed issues with josn loader
Ragansu Jan 23, 2025
41dd332
lint fix
Ragansu Jan 23, 2025
a8400d8
Fixed issue with json loaded, and shared hits eta cuts,
Ragansu Jan 24, 2025
ee23388
minor change in minScore
Ragansu Jan 24, 2025
5edccdc
added minUnshared
Ragansu Jan 25, 2025
5f56dd4
lint fix reco
Ragansu Jan 25, 2025
cf7c033
added sharedHItsFlag for detectors
Ragansu Jan 25, 2025
f80adfa
removed couts again
Ragansu Jan 28, 2025
89615b4
Merge branch 'main' into feat_eta_based_cuts
Ragansu Jan 28, 2025
e302dac
Merge branch 'main' into feat_eta_based_cuts
Ragansu Jan 29, 2025
ee0a36a
Error handling + doc
Ragansu Jan 29, 2025
541f3f7
fixed doc issue
Ragansu Jan 29, 2025
3cf3136
updated the etabased cuts initialization
Ragansu Jan 29, 2025
b75d2b2
lint fix
Ragansu Jan 29, 2025
ed37831
updated etabased cuts for efficiency and easy validation
Ragansu Jan 29, 2025
b432c54
fixed issues with initializeEtaVector
Ragansu Jan 29, 2025
2a37211
switched linear search with binary search
Ragansu Jan 29, 2025
babb823
fixing signess issue
Ragansu Jan 29, 2025
0c77316
direct assignment for etaBins
Ragansu Jan 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ namespace Acts {
/// enough hits
/// 5) Remove tracks that are not good enough based on cuts Contains method for
/// data preparations

class ScoreBasedAmbiguityResolution {
public:
/// @brief Detector configuration struct : contains the configuration for each detector
Expand All @@ -50,11 +51,23 @@ class ScoreBasedAmbiguityResolution {
int outliersScoreWeight = 0;
int otherScoreWeight = 0;

std::size_t minHits = 0;
// the eta bins for the detector
std::vector<double> etaBins = {-5, 5};

// the minimum number of hits for each detector for each eta bin
std::vector<std::size_t> minHitsPerEta = {0};

// the maximum number of holes for each detector for each eta bin
std::vector<std::size_t> maxHolesPerEta = {0};

// the maximum number of outliers for each detector for each eta bin
std::vector<std::size_t> maxOutliersPerEta = {0};

// the maximum number of shared hits for each detector for each eta bin
std::vector<std::size_t> maxSharedHitsPerEta = {0};

Ragansu marked this conversation as resolved.
Show resolved Hide resolved
std::size_t maxHits = 0;
std::size_t maxHoles = 0;
std::size_t maxOutliers = 0;
std::size_t maxSharedHits = 0;

/// if true, the shared hits are considered as bad hits for this detector
bool sharedHitsFlag = false;
Expand Down Expand Up @@ -107,15 +120,8 @@ class ScoreBasedAmbiguityResolution {
std::size_t maxSharedTracksPerMeasurement = 10;
/// maximum number of shared hit per track
std::size_t maxShared = 5;

double pTMin = 0 * UnitConstants::GeV;
double pTMax = 1e5 * UnitConstants::GeV;

double phiMin = -std::numbers::pi * UnitConstants::rad;
double phiMax = std::numbers::pi * UnitConstants::rad;

double etaMin = -5;
double etaMax = 5;
/// minimum number of unshared hits per track
std::size_t minUnshared = 5;

// if true, the ambiguity score is computed based on a different function.
bool useAmbiguityFunction = false;
Expand Down Expand Up @@ -185,6 +191,16 @@ class ScoreBasedAmbiguityResolution {
const OptionalCuts<typename track_container_t::ConstTrackProxy>&
optionalCuts = {}) const;

/// Rejects Tracks based on eta dependent cuts.
///
/// @param detector is the detector configuration object
/// @param trackFeatures is the trackFeatures object for a specific detector
/// @param eta is the eta of the track
/// @return true if the track is rejected, false otherwise
bool etaBasedCuts(const DetectorConfig& detector,
const TrackFeatures& trackFeatures,
const double& eta) const;

/// Remove hits that are not good enough for each track and removes tracks
/// that have a score below a certain threshold or not enough hits.
///
Expand Down Expand Up @@ -221,6 +237,16 @@ class ScoreBasedAmbiguityResolution {
const OptionalCuts<typename track_container_t::ConstTrackProxy>&
optionalCuts = {}) const;

/// Get the value at a specific eta bin.
///
/// @param cuts is the input vector of cuts
/// @param etaBinSize is the size of the eta bin
/// @param binIndex is the index of the bin
/// @return the value of cut at the specific eta bin
static std::size_t getValueAtEta(std::vector<std::size_t> cuts,
std::size_t etaBinSize,
std::size_t binIndex);

private:
Config m_cfg;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,40 +89,7 @@ std::vector<double> Acts::ScoreBasedAmbiguityResolution::simpleScore(
// get the trackFeatures map for the track
const auto& trackFeaturesVector = trackFeaturesVectors[iTrack];
double score = 1;
auto pT = Acts::VectorHelpers::perp(track.momentum());
auto eta = Acts::VectorHelpers::eta(track.momentum());
auto phi = Acts::VectorHelpers::phi(track.momentum());
// cuts on pT
if (pT < m_cfg.pTMin || pT > m_cfg.pTMax) {
score = 0;
iTrack++;
trackScore.push_back(score);
ACTS_DEBUG("Track: " << iTrack
<< " has score = 0, due to pT cuts --- pT = " << pT);
continue;
}

// cuts on phi
if (phi > m_cfg.phiMax || phi < m_cfg.phiMin) {
score = 0;
iTrack++;
trackScore.push_back(score);
ACTS_DEBUG("Track: " << iTrack
<< " has score = 0, due to phi cuts --- phi = "
<< phi);
continue;
}

// cuts on eta
if (eta > m_cfg.etaMax || eta < m_cfg.etaMin) {
score = 0;
iTrack++;
trackScore.push_back(score);
ACTS_DEBUG("Track: " << iTrack
<< " has score = 0, due to eta cuts --- eta = "
<< eta);
continue;
}

// cuts on optional cuts
for (const auto& cutFunction : optionalCuts.cuts) {
Expand All @@ -140,22 +107,22 @@ std::vector<double> Acts::ScoreBasedAmbiguityResolution::simpleScore(
ACTS_DEBUG("Track: " << iTrack << " score : " << score);
continue;
}

// Reject tracks which didn't pass the detector cuts.
for (std::size_t detectorId = 0; detectorId < m_cfg.detectorConfigs.size();
detectorId++) {
const auto& detector = m_cfg.detectorConfigs.at(detectorId);

const auto& trackFeatures = trackFeaturesVector[detectorId];

ACTS_DEBUG("---> Found summary information");
ACTS_DEBUG("---> Detector ID: " << detectorId);
ACTS_DEBUG("---> Number of hits: " << trackFeatures.nHits);
ACTS_DEBUG("---> Number of holes: " << trackFeatures.nHoles);
ACTS_DEBUG("---> Number of outliers: " << trackFeatures.nOutliers);
ACTS_VERBOSE("---> Found summary information");
ACTS_VERBOSE("---> Detector ID: " << detectorId);
ACTS_VERBOSE("---> Number of hits: " << trackFeatures.nHits);
ACTS_VERBOSE("---> Number of holes: " << trackFeatures.nHoles);
ACTS_VERBOSE("---> Number of outliers: " << trackFeatures.nOutliers);

if ((trackFeatures.nHits < detector.minHits) ||
(trackFeatures.nHoles > detector.maxHoles) ||
(trackFeatures.nOutliers > detector.maxOutliers)) {
// eta based cuts
if (etaBasedCuts(detector, trackFeatures, eta)) {
score = 0;
ACTS_DEBUG("Track: " << iTrack
<< " has score = 0, due to detector cuts");
Expand All @@ -170,9 +137,7 @@ std::vector<double> Acts::ScoreBasedAmbiguityResolution::simpleScore(
continue;
}

// real scoring starts here
// if the ambiguity scoring function is used, the score is processed with a
// different algorithm than the simple score.
// All cuts passed, now start scoring the track

ACTS_VERBOSE("Using Simple Scoring function");

Expand Down Expand Up @@ -241,38 +206,6 @@ std::vector<double> Acts::ScoreBasedAmbiguityResolution::ambiguityScore(
double score = 1;
auto pT = Acts::VectorHelpers::perp(track.momentum());
auto eta = Acts::VectorHelpers::eta(track.momentum());
auto phi = Acts::VectorHelpers::phi(track.momentum());
// cuts on pT
if (pT < m_cfg.pTMin || pT > m_cfg.pTMax) {
score = 0;
iTrack++;
trackScore.push_back(score);
ACTS_DEBUG("Track: " << iTrack
<< " has score = 0, due to pT cuts --- pT = " << pT);
continue;
}

// cuts on phi
if (phi > m_cfg.phiMax || phi < m_cfg.phiMin) {
score = 0;
iTrack++;
trackScore.push_back(score);
ACTS_DEBUG("Track: " << iTrack
<< " has score = 0, due to phi cuts --- phi = "
<< phi);
continue;
}

// cuts on eta
if (eta > m_cfg.etaMax || eta < m_cfg.etaMin) {
score = 0;
iTrack++;
trackScore.push_back(score);
ACTS_DEBUG("Track: " << iTrack
<< " has score = 0, due to eta cuts --- eta = "
<< eta);
continue;
}

// cuts on optional cuts
for (const auto& cutFunction : optionalCuts.cuts) {
Expand All @@ -290,22 +223,22 @@ std::vector<double> Acts::ScoreBasedAmbiguityResolution::ambiguityScore(
ACTS_DEBUG("Track: " << iTrack << " score : " << score);
continue;
}

// Reject tracks which didn't pass the detector cuts.
for (std::size_t detectorId = 0; detectorId < m_cfg.detectorConfigs.size();
detectorId++) {
const auto& detector = m_cfg.detectorConfigs.at(detectorId);

const auto& trackFeatures = trackFeaturesVector[detectorId];

ACTS_DEBUG("---> Found summary information");
ACTS_DEBUG("---> Detector ID: " << detectorId);
ACTS_DEBUG("---> Number of hits: " << trackFeatures.nHits);
ACTS_DEBUG("---> Number of holes: " << trackFeatures.nHoles);
ACTS_DEBUG("---> Number of outliers: " << trackFeatures.nOutliers);
ACTS_VERBOSE("---> Found summary information");
ACTS_VERBOSE("---> Detector ID: " << detectorId);
ACTS_VERBOSE("---> Number of hits: " << trackFeatures.nHits);
ACTS_VERBOSE("---> Number of holes: " << trackFeatures.nHoles);
ACTS_VERBOSE("---> Number of outliers: " << trackFeatures.nOutliers);

if ((trackFeatures.nHits < detector.minHits) ||
(trackFeatures.nHoles > detector.maxHoles) ||
(trackFeatures.nOutliers > detector.maxOutliers)) {
// eta based cuts
if (etaBasedCuts(detector, trackFeatures, eta)) {
score = 0;
ACTS_DEBUG("Track: " << iTrack
<< " has score = 0, due to detector cuts");
Expand All @@ -320,6 +253,8 @@ std::vector<double> Acts::ScoreBasedAmbiguityResolution::ambiguityScore(
continue;
}

// All cuts passed, now start scoring the track

// start with larger score for tracks with higher pT.
score = std::log10(pT / UnitConstants::MeV) - 1.;
// pT in GeV, hence 100 MeV is minimum and gets score = 1
Expand Down Expand Up @@ -370,6 +305,7 @@ std::vector<double> Acts::ScoreBasedAmbiguityResolution::ambiguityScore(
<< " is : " << fac
<< " New score now: " << score);
}

iTrack++;

// Add the score to the vector
Expand Down Expand Up @@ -451,11 +387,24 @@ std::vector<int> Acts::ScoreBasedAmbiguityResolution::solveAmbiguity(
// Check if the track has too many shared hits to be accepted.
auto trackFeaturesVector = trackFeaturesVectors.at(iTrack);
bool trkCouldBeAccepted = true;
double eta = Acts::VectorHelpers::eta(track.momentum());

for (std::size_t detectorId = 0; detectorId < m_cfg.detectorConfigs.size();
detectorId++) {
auto detector = m_cfg.detectorConfigs.at(detectorId);

std::vector<double> etaBins = detector.etaBins;
int etaBin = 0;

for (std::size_t i = 0; i < detector.etaBins.size() - 1; ++i) {
if (eta >= etaBins[i] && eta < detector.etaBins[i + 1]) {
etaBin = i;
break;
}
}

if (trackFeaturesVector[detectorId].nSharedHits >
detector.maxSharedHits) {
getValueAtEta(detector.maxSharedHitsPerEta, etaBins.size(), etaBin)) {
trkCouldBeAccepted = false;
break;
}
Expand All @@ -470,7 +419,7 @@ std::vector<int> Acts::ScoreBasedAmbiguityResolution::solveAmbiguity(
nTracksPerMeasurement, optionalHitSelections);
if (trkCouldBeAccepted) {
cleanTrackIndex++;
if (trackScore[iTrack] >= m_cfg.minScore) {
if (trackScore[iTrack] > m_cfg.minScore) {
goodTracks.push_back(track.index());
}
}
Expand Down Expand Up @@ -541,6 +490,18 @@ bool Acts::ScoreBasedAmbiguityResolution::getCleanedOutTracks(
ACTS_DEBUG("Track state has no reference surface");
continue;
}

std::size_t ivolume = ts.referenceSurface().geometryId().volume();
auto volume_it = m_cfg.volumeMap.find(ivolume);
if (volume_it == m_cfg.volumeMap.end()) {
ACTS_ERROR("Volume " << ivolume << "not found in the volume map");
continue;
}

std::size_t detectorID = volume_it->second;

const auto& detector = m_cfg.detectorConfigs.at(detectorID);

measurement = measurementsPerTrack[index];

auto it = nTracksPerMeasurement.find(measurement);
Expand Down Expand Up @@ -573,7 +534,8 @@ bool Acts::ScoreBasedAmbiguityResolution::getCleanedOutTracks(
else {
ACTS_DEBUG("Try to recover shared hit ");
if (nTracksShared <= m_cfg.maxSharedTracksPerMeasurement &&
trackScore > m_cfg.minScoreSharedTracks) {
trackScore > m_cfg.minScoreSharedTracks &&
!detector.sharedHitsFlag) {
ACTS_DEBUG("Accepted hit shared with " << nTracksShared << " tracks");
newMeasurementsPerTrack.push_back(measurement);
nshared++;
Expand All @@ -585,7 +547,7 @@ bool Acts::ScoreBasedAmbiguityResolution::getCleanedOutTracks(
}
}
// Check if the track has enough hits to be accepted.
if (newMeasurementsPerTrack.size() < 3) {
if (newMeasurementsPerTrack.size() < m_cfg.minUnshared) {
return false;
} else {
return true;
Expand Down
36 changes: 36 additions & 0 deletions Core/src/AmbiguityResolution/ScoreBasedAmbiguityResolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,39 @@
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

#include "Acts/AmbiguityResolution/ScoreBasedAmbiguityResolution.hpp"

std::size_t Acts::ScoreBasedAmbiguityResolution::getValueAtEta(
std::vector<std::size_t> cuts, std::size_t etaBinSize,
std::size_t binIndex) {
if (cuts.size() == etaBinSize - 1) {
return cuts[binIndex];
}

else if (cuts.size() == 1) {
return cuts[0];
}

else {
throw std::invalid_argument("Invalid cuts size. Expected 1 or " +
std::to_string(etaBinSize - 1) + ", got " +
std::to_string(cuts.size()));
}
}

bool Acts::ScoreBasedAmbiguityResolution::etaBasedCuts(
const DetectorConfig& detector, const TrackFeatures& trackFeatures,
const double& eta) const {
std::vector<double> etaBins = detector.etaBins;

auto it = std::upper_bound(etaBins.begin(), etaBins.end(), eta);
if (it == etaBins.begin() || it == etaBins.end()) {
return false; // eta out of range
}
std::size_t etaBin = std::distance(etaBins.begin(), it) - 1;
return (trackFeatures.nHits <
getValueAtEta(detector.minHitsPerEta, etaBins.size(), etaBin)) ||
(trackFeatures.nHoles >
getValueAtEta(detector.maxHolesPerEta, etaBins.size(), etaBin)) ||
(trackFeatures.nOutliers >
getValueAtEta(detector.maxOutliersPerEta, etaBins.size(), etaBin));
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,8 @@ class ScoreBasedAmbiguityResolutionAlgorithm final : public IAlgorithm {
// maximum number of shared hit per track
std::size_t maxShared = 5;

double pTMin = 0 * Acts::UnitConstants::GeV;
double pTMax = 1e5 * Acts::UnitConstants::GeV;

double phiMin = -std::numbers::pi * Acts::UnitConstants::rad;
double phiMax = std::numbers::pi * Acts::UnitConstants::rad;

double etaMin = -5;
double etaMax = 5;
// minimum number of unshared hits per track
std::size_t minUnshared = 5;

bool useAmbiguityFunction = false;
};
Expand Down
Loading
Loading