diff --git a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp index 738399a1e42..7de071592ff 100644 --- a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp +++ b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp @@ -28,6 +28,12 @@ ActsExamples::ParticleSelector::ParticleSelector(const Config& config, } m_inputParticles.initialize(m_cfg.inputParticles); + + Config defaults; + if (m_cfg.measurementsMin > defaults.measurementsMin || + m_cfg.measurementsMax < defaults.measurementsMax) { + m_inputMeasPartMap.initialize(m_cfg.inputMeasurementParticlesMap); + } m_outputParticles.initialize(m_cfg.outputParticles); ACTS_DEBUG("selection particle rho [" << m_cfg.rhoMin << "," << m_cfg.rhoMax @@ -56,6 +62,21 @@ ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( // prepare input/ output types const SimParticleContainer& inputParticles = m_inputParticles(ctx); + // Optionally construct a particles->measurement map + std::optional> + partMeasMap; + if (m_inputMeasPartMap.isInitialized()) { + const auto& measPartMap = m_inputMeasPartMap(ctx); + using InvPair = std::pair; + std::vector v(measPartMap.size()); + std::ranges::transform(measPartMap, v.begin(), [](const auto& p) { + return InvPair{p.second, p.first}; + }); + std::ranges::sort(v, std::less{}, &InvPair::first); + partMeasMap.emplace(boost::container::ordered_range_t{}, v.begin(), + v.end()); + } + std::size_t nInvalidCharge = 0; std::size_t nInvalidMeasurementCount = 0; @@ -76,8 +97,13 @@ ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( nInvalidCharge += static_cast(!validCharge); - bool validMeasurementCount = - within(p.numberOfHits(), m_cfg.measurementsMin, m_cfg.measurementsMax); + bool validMeasurementCount = true; + if (partMeasMap) { + auto [begin, end] = partMeasMap->equal_range(p.particleId()); + std::size_t nMeasurements = std::distance(begin, end); + validMeasurementCount = + within(nMeasurements, m_cfg.measurementsMin, m_cfg.measurementsMax); + } nInvalidMeasurementCount += static_cast(!validMeasurementCount); diff --git a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp index 78326844f19..6a592163648 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; + /// The input measurement particles map (optional, required if selection + /// based on number of measurements is requested). + std::string inputMeasurementParticlesMap; /// The output particles collection. std::string outputParticles; @@ -75,6 +79,8 @@ class ParticleSelector final : public IAlgorithm { Config m_cfg; ReadDataHandle m_inputParticles{this, "InputParticles"}; + ReadDataHandle> m_inputMeasPartMap{ + this, "InputMeasPartMap"}; WriteDataHandle m_outputParticles{this, "OutputParticles"}; diff --git a/Examples/Framework/include/ActsExamples/EventData/SimParticle.hpp b/Examples/Framework/include/ActsExamples/EventData/SimParticle.hpp index cfcf8a5e25e..0fdbb1f9966 100644 --- a/Examples/Framework/include/ActsExamples/EventData/SimParticle.hpp +++ b/Examples/Framework/include/ActsExamples/EventData/SimParticle.hpp @@ -161,8 +161,8 @@ class SimParticle final { /// Accumulated path within material measured in interaction lengths. double pathInL0() const { return final().pathInL0(); } - /// Number of hits. - std::uint32_t numberOfHits() const { return final().numberOfHits(); } + /// Number of simulated hits (not measurements). + std::uint32_t numberOfSimHits() const { return final().numberOfHits(); } /// Particle outcome. ActsFatras::ParticleOutcome outcome() const { return final().outcome(); } diff --git a/Examples/Io/Json/src/TestSurfaceJsonRoundtrip.cpp b/Examples/Io/Json/src/TestSurfaceJsonRoundtrip.cpp new file mode 100644 index 00000000000..ce4f3ed7eaa --- /dev/null +++ b/Examples/Io/Json/src/TestSurfaceJsonRoundtrip.cpp @@ -0,0 +1,37 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "ActsExamples/Io/Json/JsonSurfacesReader.hpp" +#include + +#include + +#include + +void writeSurfaces( + std::ostream &os, + const std::vector> &jSurfaces) { + nlohmann::json j = nlohmann::json::array(); + + for (const auto &jSurface : jSurfaces) { + j.push_back( + Acts::SurfaceJsonConverter::toJson(Acts::GeometryContext{}, *jSurface)); + } + + os << j; +} + +int main(int argc, char **argv) { + std::vector args(argv, argv + argc); + + auto surfaces = + ActsExamples::JsonSurfacesReader::readVector({args.at(1), {}}); + + std::ofstream outfile("output_surfaces.json"); + writeSurfaces(outfile, surfaces); +} diff --git a/Examples/Io/Root/src/RootParticleWriter.cpp b/Examples/Io/Root/src/RootParticleWriter.cpp index ac6d47d10da..d4e1186892a 100644 --- a/Examples/Io/Root/src/RootParticleWriter.cpp +++ b/Examples/Io/Root/src/RootParticleWriter.cpp @@ -143,7 +143,7 @@ ActsExamples::ProcessCode ActsExamples::RootParticleWriter::writeT( Acts::clampValue(particle.pathInX0() / Acts::UnitConstants::mm)); m_pathInL0.push_back( Acts::clampValue(particle.pathInL0() / Acts::UnitConstants::mm)); - m_numberOfHits.push_back(particle.numberOfHits()); + m_numberOfHits.push_back(particle.numberOfSimHits()); m_outcome.push_back(static_cast(particle.outcome())); } diff --git a/Examples/Python/python/acts/examples/simulation.py b/Examples/Python/python/acts/examples/simulation.py index 21c4149661f..143d8296a10 100644 --- a/Examples/Python/python/acts/examples/simulation.py +++ b/Examples/Python/python/acts/examples/simulation.py @@ -356,6 +356,7 @@ def addParticleSelection( config: ParticleSelectorConfig, inputParticles: str, outputParticles: str, + inputMeasurementParticlesMap: str = "", logLevel: Optional[acts.logging.Level] = None, ) -> None: """ @@ -401,6 +402,7 @@ def addParticleSelection( ), level=customLogLevel(), inputParticles=inputParticles, + inputMeasurementParticlesMap=inputMeasurementParticlesMap, outputParticles=outputParticles, ) ) diff --git a/Examples/Python/src/TruthTracking.cpp b/Examples/Python/src/TruthTracking.cpp index 3f0d8a0915a..ae417113d13 100644 --- a/Examples/Python/src/TruthTracking.cpp +++ b/Examples/Python/src/TruthTracking.cpp @@ -62,6 +62,7 @@ void addTruthTracking(Context& ctx) { ACTS_PYTHON_STRUCT_BEGIN(c, Config); ACTS_PYTHON_MEMBER(inputParticles); + ACTS_PYTHON_MEMBER(inputMeasurementParticlesMap); ACTS_PYTHON_MEMBER(outputParticles); ACTS_PYTHON_MEMBER(rhoMin); ACTS_PYTHON_MEMBER(rhoMax);