From 3ca47bdc8137fe31dce8ef16f79064ecaa456499 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Wed, 4 Dec 2024 17:00:52 +0100 Subject: [PATCH] fix: Distinguish between hits and measurements in `ParticleSelector` in Examples --- .../TruthTracking/ParticleSelector.cpp | 43 +++++++++++++++---- .../TruthTracking/ParticleSelector.hpp | 11 ++++- .../Python/python/acts/examples/simulation.py | 3 ++ Examples/Python/src/TruthTracking.cpp | 2 + 4 files changed, 50 insertions(+), 9 deletions(-) diff --git a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp index b4ef0928da0..ac52c55d495 100644 --- a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp +++ b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp @@ -8,8 +8,8 @@ #include "ActsExamples/TruthTracking/ParticleSelector.hpp" -#include "Acts/Definitions/Common.hpp" #include "Acts/Utilities/VectorHelpers.hpp" +#include "ActsExamples/EventData/Index.hpp" #include "ActsExamples/EventData/SimParticle.hpp" #include "ActsExamples/Framework/AlgorithmContext.hpp" @@ -17,8 +17,10 @@ #include #include -ActsExamples::ParticleSelector::ParticleSelector(const Config& config, - Acts::Logging::Level level) +namespace ActsExamples { + +ParticleSelector::ParticleSelector(const Config& config, + Acts::Logging::Level level) : IAlgorithm("ParticleSelector", level), m_cfg(config) { if (m_cfg.inputParticles.empty()) { throw std::invalid_argument("Missing input particles collection"); @@ -28,8 +30,17 @@ ActsExamples::ParticleSelector::ParticleSelector(const Config& config, } m_inputParticles.initialize(m_cfg.inputParticles); + m_inputParticleMeasurementsMap.maybeInitialize( + m_cfg.inputParticleMeasurementsMap); m_outputParticles.initialize(m_cfg.outputParticles); + if (m_inputParticleMeasurementsMap.isInitialized() && + (m_cfg.measurementsMin > 0 || + m_cfg.measurementsMax < std::numeric_limits::max())) { + throw std::invalid_argument( + "Measurement-based cuts require the inputMeasurementParticlesMap"); + } + ACTS_DEBUG("selection particle rho [" << m_cfg.rhoMin << "," << m_cfg.rhoMax << ")"); ACTS_DEBUG("selection particle |z| [" << m_cfg.absZMin << "," << m_cfg.absZMax @@ -46,6 +57,8 @@ ActsExamples::ParticleSelector::ParticleSelector(const Config& config, << ")"); ACTS_DEBUG("selection particle m [" << m_cfg.mMin << "," << m_cfg.mMax << ")"); + ACTS_DEBUG("selection particle hits [" << m_cfg.hitsMin << "," + << m_cfg.hitsMax << ")"); ACTS_DEBUG("selection particle measurements [" << m_cfg.measurementsMin << "," << m_cfg.measurementsMax << ")"); ACTS_DEBUG("remove charged particles " << m_cfg.removeCharged); @@ -59,12 +72,18 @@ ActsExamples::ParticleSelector::ParticleSelector(const Config& config, << m_cfg.maxPrimaryVertexId << ")"); } -ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( - const AlgorithmContext& ctx) const { +ProcessCode ParticleSelector::execute(const AlgorithmContext& ctx) const { // prepare input/ output types const SimParticleContainer& inputParticles = m_inputParticles(ctx); + const static InverseMultimap emptyMeasurementParticlesMap; + const InverseMultimap& inputMeasurementParticlesMap = + m_inputParticleMeasurementsMap.isInitialized() + ? m_inputParticleMeasurementsMap(ctx) + : emptyMeasurementParticlesMap; + std::size_t nInvalidCharge = 0; + std::size_t nInvalidHitCount = 0; std::size_t nInvalidMeasurementCount = 0; // helper functions to select tracks @@ -87,9 +106,14 @@ ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( nInvalidCharge += static_cast(!validCharge); - bool validMeasurementCount = - within(p.numberOfHits(), m_cfg.measurementsMin, m_cfg.measurementsMax); + const bool validHitCount = + within(p.numberOfHits(), m_cfg.hitsMin, m_cfg.hitsMax); + nInvalidHitCount += static_cast(!validHitCount); + const std::size_t measurementCount = + inputMeasurementParticlesMap.count(p.particleId()); + const bool validMeasurementCount = + within(measurementCount, m_cfg.measurementsMin, m_cfg.measurementsMax); nInvalidMeasurementCount += static_cast(!validMeasurementCount); @@ -103,7 +127,7 @@ ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( } return validPdg && validCharge && validSecondary && validPrimaryVertexId && - validMeasurementCount && + validHitCount && validMeasurementCount && within(p.transverseMomentum(), m_cfg.ptMin, m_cfg.ptMax) && within(std::abs(eta), m_cfg.absEtaMin, m_cfg.absEtaMax) && within(eta, m_cfg.etaMin, m_cfg.etaMax) && @@ -132,6 +156,7 @@ ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( << outputParticles.size() << " from " << inputParticles.size() << " particles"); ACTS_DEBUG("filtered out because of charge: " << nInvalidCharge); + ACTS_DEBUG("filtered out because of hit count: " << nInvalidHitCount); ACTS_DEBUG("filtered out because of measurement count: " << nInvalidMeasurementCount); @@ -139,3 +164,5 @@ ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( return ProcessCode::SUCCESS; } + +} // namespace ActsExamples diff --git a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp index 4bd465d1b4d..4c57c5cbeef 100644 --- a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp +++ b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp @@ -9,6 +9,7 @@ #pragma once #include "Acts/Utilities/Logger.hpp" +#include "ActsExamples/EventData/Index.hpp" #include "ActsExamples/EventData/SimParticle.hpp" #include "ActsExamples/Framework/DataHandle.hpp" #include "ActsExamples/Framework/IAlgorithm.hpp" @@ -26,6 +27,9 @@ class ParticleSelector final : public IAlgorithm { struct Config { /// The input particles collection. std::string inputParticles; + /// (Optionally) The input particle measurements map. Only required for + /// measurement-based cuts. + std::string inputParticleMeasurementsMap; /// The output particles collection. std::string outputParticles; @@ -51,7 +55,10 @@ class ParticleSelector final : public IAlgorithm { // Rest mass cuts double mMin = 0; double mMax = std::numeric_limits::infinity(); - /// Measurement number cuts + // Hit count cuts + std::size_t hitsMin = 0; + std::size_t hitsMax = std::numeric_limits::max(); + // Measurement number cuts std::size_t measurementsMin = 0; std::size_t measurementsMax = std::numeric_limits::max(); /// Remove charged particles. @@ -81,6 +88,8 @@ class ParticleSelector final : public IAlgorithm { Config m_cfg; ReadDataHandle m_inputParticles{this, "InputParticles"}; + ReadDataHandle> m_inputParticleMeasurementsMap{ + this, "InputParticleMeasurementsMap"}; WriteDataHandle m_outputParticles{this, "OutputParticles"}; diff --git a/Examples/Python/python/acts/examples/simulation.py b/Examples/Python/python/acts/examples/simulation.py index 2a8994ecf57..479a1e1fb1b 100644 --- a/Examples/Python/python/acts/examples/simulation.py +++ b/Examples/Python/python/acts/examples/simulation.py @@ -41,6 +41,7 @@ "absEta", # (min,max) "pt", # (min,max) "m", # (min,max) + "hits", # (min,max) "measurements", # (min,max) "removeCharged", # bool "removeNeutral", # bool @@ -393,6 +394,8 @@ def addParticleSelection( ptMax=config.pt[1], mMin=config.m[0], mMax=config.m[1], + hitsMin=config.hits[0], + hitsMax=config.hits[1], measurementsMin=config.measurements[0], measurementsMax=config.measurements[1], removeCharged=config.removeCharged, diff --git a/Examples/Python/src/TruthTracking.cpp b/Examples/Python/src/TruthTracking.cpp index 4799d93dbdb..4d3569f4656 100644 --- a/Examples/Python/src/TruthTracking.cpp +++ b/Examples/Python/src/TruthTracking.cpp @@ -84,6 +84,8 @@ void addTruthTracking(Context& ctx) { ACTS_PYTHON_MEMBER(mMax); ACTS_PYTHON_MEMBER(ptMin); ACTS_PYTHON_MEMBER(ptMax); + ACTS_PYTHON_MEMBER(hitsMin); + ACTS_PYTHON_MEMBER(hitsMax); ACTS_PYTHON_MEMBER(measurementsMin); ACTS_PYTHON_MEMBER(measurementsMax); ACTS_PYTHON_MEMBER(removeCharged);