From f6e95c2999adbf5188af7ce1dcf8a1671168bb1a Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Thu, 21 Nov 2024 22:43:24 +0100 Subject: [PATCH 1/8] refactor: Reduce abort output in GX2F to DEBUG (#3888) I think outputs that run on every single event should generally not be INFO. --- Core/include/Acts/TrackFitting/GlobalChiSquareFitter.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/include/Acts/TrackFitting/GlobalChiSquareFitter.hpp b/Core/include/Acts/TrackFitting/GlobalChiSquareFitter.hpp index 8442071a23f..a7b28d5e8f3 100644 --- a/Core/include/Acts/TrackFitting/GlobalChiSquareFitter.hpp +++ b/Core/include/Acts/TrackFitting/GlobalChiSquareFitter.hpp @@ -1408,9 +1408,9 @@ class Gx2Fitter { if ((gx2fOptions.relChi2changeCutOff != 0) && (nUpdate > 0) && (std::abs(extendedSystem.chi2() / oldChi2sum - 1) < gx2fOptions.relChi2changeCutOff)) { - ACTS_INFO("Abort with relChi2changeCutOff after " - << nUpdate + 1 << "/" << gx2fOptions.nUpdateMax - << " iterations."); + ACTS_DEBUG("Abort with relChi2changeCutOff after " + << nUpdate + 1 << "/" << gx2fOptions.nUpdateMax + << " iterations."); updateGx2fCovarianceParams(fullCovariancePredicted, extendedSystem); break; } From 6ff7d492dc0b8cbc65487edbc7c0a6fe7e3bedf3 Mon Sep 17 00:00:00 2001 From: ssdetlab <113530373+ssdetlab@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:59:53 +0200 Subject: [PATCH 2/8] feat: Track parameters lookup estimation examples (#3823) The PR adding the simulation based track parameter estimation. The algorithm runs the `Fatras` simulation of the detector setup. A set of grids is imposed onto the user-defined reference layers of the tracking detector (e.g. first tracking layers sensitive surfaces). `CurvilinearTrackParameters` at the vertex and the reference tracking layers are recorded for the simulated particles and stored into the bins of the grids. After the simulation is finished, the contents of the grids' bins are averaged and the grids containing the correspondence between the particles' intersection points at the reference layers, track parameters at the vertex and track parameters at the reference layers are constructed. The constructed grids are stored into the json files. The grids are then readout and used for track parameters estimation in seeding algorithms, e.g. connected to the `PathSeeder`. This PR contains the lookup generation part of the algorithm. When the interfaces, realisation and the general idea are agreed upon, the second part with the validation of the estimated lookups is going to be put up. --- .../EventData/detail/TrackParametersUtils.hpp | 49 ++++ .../TrackParamsLookupAccumulator.hpp | 179 ++++++++++++++ .../Algorithms/TrackFinding/CMakeLists.txt | 1 + .../TrackFinding/ITrackParamsLookupReader.hpp | 27 +++ .../TrackFinding/ITrackParamsLookupWriter.hpp | 27 +++ .../TrackParamsLookupEstimation.hpp | 78 +++++++ .../TrackFinding/TrackParamsLookupTable.hpp | 44 ++++ .../src/TrackParamsLookupEstimation.cpp | 104 +++++++++ .../Io/Json/JsonTrackParamsLookupReader.hpp | 101 ++++++++ .../Io/Json/JsonTrackParamsLookupWriter.hpp | 69 ++++++ Examples/Python/src/Json.cpp | 51 ++++ Examples/Python/src/Output.cpp | 10 + Examples/Python/src/TrackFinding.cpp | 6 + ...elescope_track_params_lookup_generation.py | 111 +++++++++ .../Json/TrackParametersJsonConverter.hpp | 31 +-- .../Core/TrackFinding/CMakeLists.txt | 1 + .../TrackParamsLookupAccumulatorTests.cpp | 221 ++++++++++++++++++ 17 files changed, 1087 insertions(+), 23 deletions(-) create mode 100644 Core/include/Acts/EventData/detail/TrackParametersUtils.hpp create mode 100644 Core/include/Acts/TrackFinding/TrackParamsLookupAccumulator.hpp create mode 100644 Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/ITrackParamsLookupReader.hpp create mode 100644 Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/ITrackParamsLookupWriter.hpp create mode 100644 Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackParamsLookupEstimation.hpp create mode 100644 Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackParamsLookupTable.hpp create mode 100644 Examples/Algorithms/TrackFinding/src/TrackParamsLookupEstimation.cpp create mode 100644 Examples/Io/Json/include/ActsExamples/Io/Json/JsonTrackParamsLookupReader.hpp create mode 100644 Examples/Io/Json/include/ActsExamples/Io/Json/JsonTrackParamsLookupWriter.hpp create mode 100644 Examples/Scripts/Python/telescope_track_params_lookup_generation.py create mode 100644 Tests/UnitTests/Core/TrackFinding/TrackParamsLookupAccumulatorTests.cpp diff --git a/Core/include/Acts/EventData/detail/TrackParametersUtils.hpp b/Core/include/Acts/EventData/detail/TrackParametersUtils.hpp new file mode 100644 index 00000000000..2efcef0e763 --- /dev/null +++ b/Core/include/Acts/EventData/detail/TrackParametersUtils.hpp @@ -0,0 +1,49 @@ +// 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/. + +#pragma once + +#include "Acts/EventData/GenericBoundTrackParameters.hpp" +#include "Acts/EventData/TrackParametersConcept.hpp" + +namespace Acts::detail { + +/// @brief Shorthand for Bound or Free track parameters +template +concept isBoundOrFreeTrackParams = + Acts::FreeTrackParametersConcept || + Acts::BoundTrackParametersConcept; + +/// @brief Shorthand for GenericBoundTrackParameters +template +concept isGenericBoundTrackParams = + std::same_as>; + +/// @brief Concept that restricts the type of the +/// accumulation grid cell +template +concept TrackParamsGrid = requires { + typename grid_t::value_type::first_type; + typename grid_t::value_type::second_type; + + requires isBoundOrFreeTrackParams< + typename grid_t::value_type::first_type::element_type>; + requires isBoundOrFreeTrackParams< + typename grid_t::value_type::second_type::element_type>; + + requires requires(typename grid_t::value_type val) { + { + val.first + } -> std::same_as< + std::shared_ptr&>; + { val.second } -> std::same_as; + }; +}; + +} // namespace Acts::detail diff --git a/Core/include/Acts/TrackFinding/TrackParamsLookupAccumulator.hpp b/Core/include/Acts/TrackFinding/TrackParamsLookupAccumulator.hpp new file mode 100644 index 00000000000..a1e1173335d --- /dev/null +++ b/Core/include/Acts/TrackFinding/TrackParamsLookupAccumulator.hpp @@ -0,0 +1,179 @@ +// 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/. + +#pragma once + +#include "Acts/EventData/detail/TrackParametersUtils.hpp" +#include "Acts/Geometry/GeometryContext.hpp" + +#include +#include +#include +#include +#include + +namespace Acts { + +/// @brief Class to accumulate and average track lookup tables +/// +/// @tparam Grid type for track parameters accumulation +/// +/// This class is used to accumulate track parameters in +/// reference layer grids and average them to create a lookup +/// table for track parameter estimation in seeding +/// +/// @note Geometry context is left to be handled by the user +/// outside of accumulation +template +class TrackParamsLookupAccumulator { + public: + using LookupGrid = grid_t; + using TrackParameters = typename std::pointer_traits< + typename grid_t::value_type::first_type>::element_type; + + /// @brief Constructor + explicit TrackParamsLookupAccumulator(grid_t grid) + : m_grid(std::move(grid)) {} + + /// @brief Add track parameters to the accumulator + /// + /// @param ipTrackParameters Track parameters at the IP + /// @param refTrackParameters Track parameters at the reference layer + /// @param position Local position of the track hit on the reference layer + void addTrack(const TrackParameters& ipTrackParameters, + const TrackParameters& refTrackParameters, + const Vector2& position) { + std::lock_guard lock(m_gridMutex); + + auto bin = m_grid.localBinsFromPosition(position); + + if (m_countGrid[bin] == 0) { + m_grid.atLocalBins(bin).first = + std::make_shared(ipTrackParameters); + m_grid.atLocalBins(bin).second = + std::make_shared(refTrackParameters); + + m_countGrid.at(bin)++; + return; + } + + *m_grid.atLocalBins(bin).first = + addTrackParameters(*m_grid.atLocalBins(bin).first, ipTrackParameters); + *m_grid.atLocalBins(bin).second = + addTrackParameters(*m_grid.atLocalBins(bin).second, refTrackParameters); + m_countGrid.at(bin)++; + } + + /// @brief Finalize the lookup table + /// + /// @return Grid with the bin track parameters averaged + LookupGrid finalizeLookup() { + auto meanTrack = [&](const TrackParameters& track, std::size_t count) { + if constexpr (detail::isGenericBoundTrackParams) { + Acts::GeometryContext gctx; + + auto res = TrackParameters::create( + track.referenceSurface().getSharedPtr(), gctx, + track.fourPosition(gctx) / count, track.momentum().normalized(), + count * track.charge() / track.momentum().norm(), + track.covariance(), track.particleHypothesis()); + + if (!res.ok()) { + throw std::invalid_argument("Bound track grid finalization failed"); + } + return res.value(); + } else { + return TrackParameters(track.fourPosition() / count, + track.momentum().normalized(), + count * track.charge() / track.momentum().norm(), + track.covariance(), track.particleHypothesis()); + } + }; + + for (auto [bin, count] : m_countGrid) { + if (count == 0) { + continue; + } + *m_grid.atLocalBins(bin).first = + meanTrack(*m_grid.atLocalBins(bin).first, count); + *m_grid.atLocalBins(bin).second = + meanTrack(*m_grid.atLocalBins(bin).second, count); + } + + return m_grid; + } + + private: + /// @brief Add two track parameters + /// + /// @param a First track parameter in the sum + /// @param b Second track parameter in the sum + /// + /// @return Sum of track parameters a + b + /// + /// @note Covariances of the track parameters + /// are not added and instead assumed to be + /// generated by the same random process for + /// both a and b, making its averaging redundant + TrackParameters addTrackParameters(const TrackParameters& a, + const TrackParameters& b) { + if (a.particleHypothesis() != b.particleHypothesis()) { + throw std::invalid_argument( + "Cannot accumulate track parameters with different particle " + "hypotheses"); + } + if (a.charge() != b.charge()) { + throw std::invalid_argument( + "Cannot accumulate track parameters with different charges"); + } + if constexpr (detail::isGenericBoundTrackParams) { + if (a.referenceSurface() != b.referenceSurface()) { + throw std::invalid_argument( + "Cannot accumulate bound track parameters with different reference " + "surfaces"); + } + } + + Acts::Vector3 momentum = a.momentum() + b.momentum(); + + // Assume track parameters being i.i.d. + if constexpr (detail::isGenericBoundTrackParams) { + Acts::GeometryContext gctx; + + Acts::Vector4 fourPosition = a.fourPosition(gctx) + b.fourPosition(gctx); + + auto res = TrackParameters::create( + a.referenceSurface().getSharedPtr(), gctx, fourPosition, + momentum.normalized(), a.charge() / momentum.norm(), a.covariance(), + a.particleHypothesis()); + + if (!res.ok()) { + throw std::runtime_error("Invalid bound track parameters"); + } + return res.value(); + } else { + Acts::Vector4 fourPosition = a.fourPosition() + b.fourPosition(); + return TrackParameters(fourPosition, momentum.normalized(), + a.charge() / momentum.norm(), a.covariance(), + a.particleHypothesis()); + } + } + + /// Grids to accumulate IP and reference + /// layer track parameters + LookupGrid m_grid; + + /// Mutex for protecting grid access + std::mutex m_gridMutex; + + /// Map to keep the accumulation count + /// in the occupied grid bins + std::map, std::size_t> m_countGrid; +}; + +} // namespace Acts diff --git a/Examples/Algorithms/TrackFinding/CMakeLists.txt b/Examples/Algorithms/TrackFinding/CMakeLists.txt index 38781494068..33b924e35aa 100644 --- a/Examples/Algorithms/TrackFinding/CMakeLists.txt +++ b/Examples/Algorithms/TrackFinding/CMakeLists.txt @@ -10,6 +10,7 @@ add_library( src/TrackParamsEstimationAlgorithm.cpp src/MuonHoughSeeder.cpp src/GbtsSeedingAlgorithm.cpp + src/TrackParamsLookupEstimation.cpp ) target_include_directories( diff --git a/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/ITrackParamsLookupReader.hpp b/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/ITrackParamsLookupReader.hpp new file mode 100644 index 00000000000..5777f90ef18 --- /dev/null +++ b/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/ITrackParamsLookupReader.hpp @@ -0,0 +1,27 @@ +// 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/. + +#pragma once + +#include "ActsExamples/TrackFinding/TrackParamsLookupTable.hpp" + +namespace ActsExamples { + +/// @brief Interface for reading track parameter lookup tables +class ITrackParamsLookupReader { + public: + /// Virtual Destructor + virtual ~ITrackParamsLookupReader() = default; + + /// Reader method + /// + /// @param path the path to the file to read + virtual TrackParamsLookup readLookup(const std::string& path) const = 0; +}; + +} // namespace ActsExamples diff --git a/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/ITrackParamsLookupWriter.hpp b/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/ITrackParamsLookupWriter.hpp new file mode 100644 index 00000000000..9cddadae062 --- /dev/null +++ b/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/ITrackParamsLookupWriter.hpp @@ -0,0 +1,27 @@ +// 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/. + +#pragma once + +#include "ActsExamples/TrackFinding/TrackParamsLookupTable.hpp" + +namespace ActsExamples { + +/// @brief Interface for writing track parameter lookup tables +class ITrackParamsLookupWriter { + public: + /// Virtual Destructor + virtual ~ITrackParamsLookupWriter() = default; + + /// Writer method + /// + /// @param lookup track lookup to write + virtual void writeLookup(const TrackParamsLookup& lookup) const = 0; +}; + +} // namespace ActsExamples diff --git a/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackParamsLookupEstimation.hpp b/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackParamsLookupEstimation.hpp new file mode 100644 index 00000000000..e50991cd944 --- /dev/null +++ b/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackParamsLookupEstimation.hpp @@ -0,0 +1,78 @@ +// 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/. + +#pragma once + +#include "Acts/TrackFinding/TrackParamsLookupAccumulator.hpp" +#include "ActsExamples/EventData/SimHit.hpp" +#include "ActsExamples/EventData/SimParticle.hpp" +#include "ActsExamples/Framework/DataHandle.hpp" +#include "ActsExamples/Framework/IAlgorithm.hpp" +#include "ActsExamples/TrackFinding/ITrackParamsLookupWriter.hpp" + +#include + +namespace ActsExamples { + +/// @brief Algorithm to estimate track parameters lookup tables +/// +/// This algorithm is used to estimate track parameters lookup tables +/// for track parameter estimation in seeding. The algorithm imposes +/// grids onto the reference tracking layers and accumulates track +/// parameters in the grid bins. The track parameters are then averaged +/// to create a lookup table for track parameter estimation in seeding. +class TrackParamsLookupEstimation : public IAlgorithm { + public: + using TrackParamsLookupAccumulator = + Acts::TrackParamsLookupAccumulator; + + /// @brief Nested configuration struct + struct Config { + /// Reference tracking layers + std::unordered_map + refLayers; + /// Binning of the grid to be emposed + /// onto the reference layers + std::pair bins; + /// Input SimHit container + std::string inputHits = "InputHits"; + /// Input SimParticle container + std::string inputParticles = "InputParticles"; + /// Track lookup writers + std::vector> + trackLookupGridWriters{}; + }; + + /// @brief Constructor + TrackParamsLookupEstimation(const Config& config, Acts::Logging::Level level); + + /// @brief The execute method + ProcessCode execute(const AlgorithmContext& ctx) const override; + + ProcessCode finalize() override; + + /// Get readonly access to the config parameters + const Config& config() const { return m_cfg; } + + private: + /// Configuration + Config m_cfg; + + /// Input data handles + ReadDataHandle m_inputParticles{this, + "InputSimParticles"}; + + ReadDataHandle m_inputSimHits{this, "InputSimHits"}; + + /// Accumulators for the track parameters + std::unordered_map> + m_accumulators; +}; + +} // namespace ActsExamples diff --git a/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackParamsLookupTable.hpp b/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackParamsLookupTable.hpp new file mode 100644 index 00000000000..5b9c1fabd83 --- /dev/null +++ b/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackParamsLookupTable.hpp @@ -0,0 +1,44 @@ +// 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/. + +#pragma once + +#include "Acts/EventData/TrackParameters.hpp" +#include "Acts/Utilities/Grid.hpp" +#include "Acts/Utilities/GridAxisGenerators.hpp" + +#include +#include + +namespace ActsExamples { + +using TrackParamsLookupPair = + std::pair, + std::shared_ptr>; + +/// @brief Track parameters lookup table axis used +/// in the track estimation algorithm +using TrackParamsLookupAxis = + Acts::Axis; + +/// @brief Track parameters lookup table axis generator +/// used in the track estimation algorithm +using TrackParamsLookupAxisGen = Acts::GridAxisGenerators::EqOpenEqOpen; + +/// @brief Lookup grid for track parameters estimation +/// in a given layer +using TrackParamsLookupGrid = + Acts::Grid; + +/// @brief Lookup table for track parameters estimation +/// in the track estimation algorithm +using TrackParamsLookup = + std::unordered_map; + +} // namespace ActsExamples diff --git a/Examples/Algorithms/TrackFinding/src/TrackParamsLookupEstimation.cpp b/Examples/Algorithms/TrackFinding/src/TrackParamsLookupEstimation.cpp new file mode 100644 index 00000000000..4e4b283ddf9 --- /dev/null +++ b/Examples/Algorithms/TrackFinding/src/TrackParamsLookupEstimation.cpp @@ -0,0 +1,104 @@ +// 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/TrackFinding/TrackParamsLookupEstimation.hpp" + +#include "Acts/Surfaces/RectangleBounds.hpp" +#include "ActsExamples/Framework/ProcessCode.hpp" + +ActsExamples::TrackParamsLookupEstimation::TrackParamsLookupEstimation( + const Config& config, Acts::Logging::Level level) + : IAlgorithm("TrackParamsLookupEstimation", level), m_cfg(config) { + // Iterate over the reference layers and create + // track parameter accumulators + for (const auto& [geoId, refSurface] : m_cfg.refLayers) { + // Get bounds to construct the accumulator grid + auto bounds = + dynamic_cast(&refSurface->bounds()); + + if (bounds == nullptr) { + throw std::invalid_argument("Only rectangle bounds supported"); + } + if (refSurface->type() != Acts::Surface::SurfaceType::Plane) { + throw std::invalid_argument("Only plane surfaces supported"); + } + + // Initialize the accumulator grid + auto halfX = bounds->halfLengthX(); + auto halfY = bounds->halfLengthY(); + + TrackParamsLookupAxisGen axisGen{ + {-halfX, halfX}, m_cfg.bins.first, {-halfY, halfY}, m_cfg.bins.second}; + + // Each reference layer has its own accumulator + m_accumulators[geoId] = std::make_unique( + TrackParamsLookupGrid(axisGen())); + } + + m_inputParticles.initialize(m_cfg.inputParticles); + m_inputSimHits.initialize(m_cfg.inputHits); +} + +ActsExamples::ProcessCode +ActsExamples::TrackParamsLookupEstimation::finalize() { + // Finiliaze the lookup tables and write them + ActsExamples::TrackParamsLookup lookup; + for (auto& [id, acc] : m_accumulators) { + lookup.insert({id, acc->finalizeLookup()}); + } + for (const auto& writer : m_cfg.trackLookupGridWriters) { + writer->writeLookup(lookup); + } + + return ActsExamples::ProcessCode::SUCCESS; +}; + +ActsExamples::ProcessCode ActsExamples::TrackParamsLookupEstimation::execute( + const ActsExamples::AlgorithmContext& ctx) const { + // Get the particles and hits + const auto& particles = m_inputParticles(ctx); + const auto& hits = m_inputSimHits(ctx); + + // Iterate over the reference layer hits and + // accumulate the track parameters + for (const auto& [geoId, refSurface] : m_cfg.refLayers) { + // Get reference layer hits + auto refLayerHits = hits.equal_range(geoId); + + for (auto hit = refLayerHits.first; hit != refLayerHits.second; ++hit) { + // Get the corresponding particle + const auto& id = hit->particleId(); + const auto& particle = particles.find(id); + + if (particle == particles.end()) { + throw std::invalid_argument("Particle not found"); + } + + // Hit stores the reference layer parameters + auto refLayerPars = Acts::CurvilinearTrackParameters( + hit->fourPosition(), hit->direction(), particle->qOverP(), + std::nullopt, particle->hypothesis()); + + // Particle stores the IP parameters + auto ipPars = Acts::CurvilinearTrackParameters( + particle->fourPosition(), particle->direction(), particle->qOverP(), + std::nullopt, particle->hypothesis()); + + // Get the local position of the hit + auto localPos = refSurface + ->globalToLocal(ctx.geoContext, hit->position(), + Acts::Vector3{0, 1, 0}) + .value(); + + // Add the track parameters to the accumulator grid + m_accumulators.at(geoId)->addTrack(ipPars, refLayerPars, localPos); + } + } + + return ActsExamples::ProcessCode::SUCCESS; +} diff --git a/Examples/Io/Json/include/ActsExamples/Io/Json/JsonTrackParamsLookupReader.hpp b/Examples/Io/Json/include/ActsExamples/Io/Json/JsonTrackParamsLookupReader.hpp new file mode 100644 index 00000000000..94abea8b903 --- /dev/null +++ b/Examples/Io/Json/include/ActsExamples/Io/Json/JsonTrackParamsLookupReader.hpp @@ -0,0 +1,101 @@ +// 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/. + +#pragma once + +#include "Acts/Plugins/Json/GridJsonConverter.hpp" +#include "Acts/Surfaces/RectangleBounds.hpp" +#include "ActsExamples/TrackFinding/ITrackParamsLookupReader.hpp" + +#include + +#include + +namespace ActsExamples { + +/// @brief Json reader for track parameter lookup tables +/// +/// This reader is used to read track parameter lookup tables +/// from a json file to be later used in track parameter estimation +/// for seeding +class JsonTrackParamsLookupReader final : public ITrackParamsLookupReader { + public: + /// @brief Nested configuration struct + struct Config { + /// Reference tracking layers + std::unordered_map + refLayers; + /// Binning of the grid to be emposed + /// onto the reference layers + std::pair bins; + }; + + explicit JsonTrackParamsLookupReader(const Config& config) : m_cfg(config) {}; + + ~JsonTrackParamsLookupReader() override = default; + + /// @brief Read the lookup from a json file + /// + /// @param path path to the json file + /// + /// @return lookup table for track parameter estimation + TrackParamsLookup readLookup(const std::string& path) const override { + // Read the json file + std::ifstream ifj(path); + nlohmann::json jLookup; + ifj >> jLookup; + + TrackParamsLookup lookup; + // Iterate over the json and deserialize the grids + for (const auto& jGrid : jLookup) { + Acts::GeometryIdentifier id(jGrid["geo_id"]); + + if (!m_cfg.refLayers.contains(id)) { + throw std::invalid_argument("Geometry identifier not found"); + } + + const auto* refSurface = m_cfg.refLayers.at(id); + + // Get bounds to construct the lookup grid + auto bounds = + dynamic_cast(&refSurface->bounds()); + + if (bounds == nullptr) { + throw std::invalid_argument("Only rectangle bounds supported"); + } + + // Axis is not deserilizable, so we need to recreate it + auto halfX = bounds->halfLengthX(); + auto halfY = bounds->halfLengthY(); + + TrackParamsLookupAxisGen axisGen{{-halfX, halfX}, + m_cfg.bins.first, + {-halfY, halfY}, + m_cfg.bins.second}; + + // Deserialize the grid + TrackParamsLookupGrid grid = + Acts::GridJsonConverter::fromJson( + jGrid["grid"], axisGen); + + lookup.try_emplace(id, std::move(grid)); + } + + return lookup; + }; + + /// Readonly access to the config + const Config& config() const { return m_cfg; } + + private: + /// The config of the writer + Config m_cfg; +}; + +} // namespace ActsExamples diff --git a/Examples/Io/Json/include/ActsExamples/Io/Json/JsonTrackParamsLookupWriter.hpp b/Examples/Io/Json/include/ActsExamples/Io/Json/JsonTrackParamsLookupWriter.hpp new file mode 100644 index 00000000000..63a2c083618 --- /dev/null +++ b/Examples/Io/Json/include/ActsExamples/Io/Json/JsonTrackParamsLookupWriter.hpp @@ -0,0 +1,69 @@ +// 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/. + +#pragma once + +#include "Acts/Plugins/Json/GridJsonConverter.hpp" +#include "ActsExamples/TrackFinding/ITrackParamsLookupWriter.hpp" + +#include + +#include + +namespace ActsExamples { + +/// @brief Json writer for track parameter lookup tables +/// +/// This writer is used to write track parameter lookup tables +/// to a json file to be later used in track parameter estimation +/// for seeding +class JsonTrackParamsLookupWriter final : public ITrackParamsLookupWriter { + public: + /// @brief Nested configuration struct + struct Config { + /// Output file name + std::string path; + }; + + /// Constructor + /// + /// @param config The configuration struct of the writer + explicit JsonTrackParamsLookupWriter(const Config& config) : m_cfg(config) {}; + + /// Virtual destructor + ~JsonTrackParamsLookupWriter() override = default; + + /// Write out track parameters lookup table + /// + /// @param lookup The lookup to write + void writeLookup(const TrackParamsLookup& lookup) const override { + nlohmann::json jLookup; + + // Iterate over the lookup and serialize the grids + for (const auto& [id, grid] : lookup) { + nlohmann::json jGrid; + jGrid["geo_id"] = id.value(); + jGrid["grid"] = Acts::GridJsonConverter::toJson(grid); + + jLookup.push_back(jGrid); + } + + // Write the json file + std::ofstream ofj(m_cfg.path, std::ios::out); + ofj << std::setw(4) << jLookup << std::endl; + }; + + /// Readonly access to the config + const Config& config() const { return m_cfg; } + + private: + /// The config of the writer + Config m_cfg; +}; + +} // namespace ActsExamples diff --git a/Examples/Python/src/Json.cpp b/Examples/Python/src/Json.cpp index be367612ac2..12baaa9f6d3 100644 --- a/Examples/Python/src/Json.cpp +++ b/Examples/Python/src/Json.cpp @@ -19,6 +19,8 @@ #include "ActsExamples/Io/Json/JsonMaterialWriter.hpp" #include "ActsExamples/Io/Json/JsonSurfacesReader.hpp" #include "ActsExamples/Io/Json/JsonSurfacesWriter.hpp" +#include "ActsExamples/Io/Json/JsonTrackParamsLookupReader.hpp" +#include "ActsExamples/Io/Json/JsonTrackParamsLookupWriter.hpp" #include #include @@ -37,6 +39,11 @@ class IMaterialDecorator; namespace ActsExamples { class IMaterialWriter; class IWriter; + +namespace Experimental { +class ITrackParamsLookupWriter; +} // namespace Experimental + } // namespace ActsExamples namespace py = pybind11; @@ -111,6 +118,50 @@ void addJson(Context& ctx) { ACTS_PYTHON_STRUCT_END(); } + { + using IWriter = ActsExamples::ITrackParamsLookupWriter; + using Writer = ActsExamples::JsonTrackParamsLookupWriter; + using Config = Writer::Config; + + auto cls = py::class_>( + mex, "JsonTrackParamsLookupWriter") + .def(py::init(), py::arg("config")) + .def("writeLookup", &Writer::writeLookup) + .def_property_readonly("config", &Writer::config); + + auto c = py::class_(cls, "Config") + .def(py::init<>()) + .def(py::init(), py::arg("path")); + + ACTS_PYTHON_STRUCT_BEGIN(c, Config); + ACTS_PYTHON_MEMBER(path); + ACTS_PYTHON_STRUCT_END(); + } + + { + using IReader = ActsExamples::ITrackParamsLookupReader; + using Reader = ActsExamples::JsonTrackParamsLookupReader; + using Config = Reader::Config; + + auto cls = py::class_>( + mex, "JsonTrackParamsLookupReader") + .def(py::init(), py::arg("config")) + .def("readLookup", &Reader::readLookup) + .def_property_readonly("config", &Reader::config); + + auto c = py::class_(cls, "Config") + .def(py::init<>()) + .def(py::init, + std::pair>(), + py::arg("refLayers"), py::arg("bins")); + + ACTS_PYTHON_STRUCT_BEGIN(c, Config); + ACTS_PYTHON_MEMBER(refLayers); + ACTS_PYTHON_MEMBER(bins); + ACTS_PYTHON_STRUCT_END(); + } + { auto cls = py::class_ #include @@ -279,6 +281,14 @@ void addOutput(Context& ctx) { py::class_>( mex, "IMaterialWriter"); + py::class_>( + mex, "ITrackParamsLookupWriter"); + + py::class_>( + mex, "ITrackParamsLookupReader"); + { using Writer = ActsExamples::RootMaterialWriter; auto w = py::class_>( diff --git a/Examples/Python/src/TrackFinding.cpp b/Examples/Python/src/TrackFinding.cpp index ad3ad364ce7..54eb7e76641 100644 --- a/Examples/Python/src/TrackFinding.cpp +++ b/Examples/Python/src/TrackFinding.cpp @@ -28,6 +28,7 @@ #include "ActsExamples/TrackFinding/SpacePointMaker.hpp" #include "ActsExamples/TrackFinding/TrackFindingAlgorithm.hpp" #include "ActsExamples/TrackFinding/TrackParamsEstimationAlgorithm.hpp" +#include "ActsExamples/TrackFinding/TrackParamsLookupEstimation.hpp" #include #include @@ -293,6 +294,11 @@ void addTrackFinding(Context& ctx) { magneticField, bFieldMin, initialSigmas, initialSigmaPtRel, initialVarInflation, noTimeVarInflation, particleHypothesis); + ACTS_PYTHON_DECLARE_ALGORITHM(ActsExamples::TrackParamsLookupEstimation, mex, + "TrackParamsLookupEstimation", refLayers, bins, + inputHits, inputParticles, + trackLookupGridWriters); + { using Alg = ActsExamples::TrackFindingAlgorithm; using Config = Alg::Config; diff --git a/Examples/Scripts/Python/telescope_track_params_lookup_generation.py b/Examples/Scripts/Python/telescope_track_params_lookup_generation.py new file mode 100644 index 00000000000..ecdffc20ec3 --- /dev/null +++ b/Examples/Scripts/Python/telescope_track_params_lookup_generation.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 + +import argparse + +import acts +import acts.examples +from acts.examples.simulation import ( + addParticleGun, + addFatras, + MomentumConfig, + EtaConfig, + PhiConfig, + ParticleConfig, +) + +u = acts.UnitConstants + + +def estimateLookup(trackingGeometry, numEvents, outputPath): + + # Set up the dipole magnetic field + field = acts.ConstantBField(acts.Vector3(50 * u.T, 0, 0)) + + # Fatras simulation of muons + rnd = acts.examples.RandomNumbers(seed=42) + + s = acts.examples.Sequencer( + events=numEvents, numThreads=1, logLevel=acts.logging.INFO + ) + + vertexGen = acts.examples.GaussianVertexGenerator( + stddev=acts.Vector4(0, 0, 0, 0), mean=acts.Vector4(0, 9, 0, 0) + ) + + addParticleGun( + s=s, + etaConfig=EtaConfig(10.0, 10.0), + phiConfig=PhiConfig(0, 0), + momentumConfig=MomentumConfig(0.5 * u.GeV, 10 * u.GeV), + particleConfig=ParticleConfig(1, acts.PdgParticle.eMuon, False), + multiplicity=1, + rnd=rnd, + vtxGen=vertexGen, + ) + + addFatras( + s, + trackingGeometry, + field, + inputParticles="particles_input", + outputSimHits="sim_hits", + rnd=rnd, + preSelectParticles=None, + ) + + # Set up the track lookup grid writer + jsonWriterConfig = acts.examples.JsonTrackParamsLookupWriter.Config(path=outputPath) + jsonWriter = acts.examples.JsonTrackParamsLookupWriter(jsonWriterConfig) + + # Set up the track estimation algorithm + surfaces = list(trackingGeometry.geoIdSurfaceMap().values()) + refSurface = surfaces[0] + refGeometryId = refSurface.geometryId() + + trackEstConfig = acts.examples.TrackParamsLookupEstimation.Config( + refLayers={refGeometryId: refSurface}, + bins=(1, 1000), + inputHits="sim_hits", + inputParticles="particles_input", + trackLookupGridWriters=[jsonWriter], + ) + trackEstAlg = acts.examples.TrackParamsLookupEstimation( + trackEstConfig, acts.logging.INFO + ) + + s.addAlgorithm(trackEstAlg) + + s.run() + + +if __name__ == "__main__": + p = argparse.ArgumentParser() + + p.add_argument( + "-n", + "--events", + type=int, + default=100000, + help="Number of events for lookup estimation", + ) + p.add_argument( + "-o", + "--output", + type=str, + default="lookup.json", + help="Output lookup file name", + ) + + args = p.parse_args() + + # Initialize the geometry + detector, trackingGeometry, decorators = acts.examples.TelescopeDetector.create( + bounds=[4, 10], + positions=[30, 60, 90], + stereos=[0, 0, 0], + binValue=2, + surfaceType=0, + ) + + # Estimate the lookup + estimateLookup(trackingGeometry, args.events, args.output) diff --git a/Plugins/Json/include/Acts/Plugins/Json/TrackParametersJsonConverter.hpp b/Plugins/Json/include/Acts/Plugins/Json/TrackParametersJsonConverter.hpp index ebf7d5c6054..d9670858566 100644 --- a/Plugins/Json/include/Acts/Plugins/Json/TrackParametersJsonConverter.hpp +++ b/Plugins/Json/include/Acts/Plugins/Json/TrackParametersJsonConverter.hpp @@ -8,28 +8,13 @@ #pragma once -#include "Acts/EventData/TrackParameters.hpp" -#include "Acts/Plugins/Json/ActsJson.hpp" +#include "Acts/Definitions/PdgParticle.hpp" +#include "Acts/EventData/GenericBoundTrackParameters.hpp" +#include "Acts/EventData/detail/TrackParametersUtils.hpp" #include "Acts/Plugins/Json/SurfaceJsonConverter.hpp" #include -namespace { - -// Alias to bound adl_serializer specialization -// only to track parameters -template -concept TrackParameters = Acts::FreeTrackParametersConcept || - Acts::BoundTrackParametersConcept; - -// Shorthand for bound track parameters -template -concept IsGenericBound = - std::same_as>; - -} // namespace - namespace Acts { NLOHMANN_JSON_SERIALIZE_ENUM(Acts::PdgParticle, @@ -67,7 +52,7 @@ namespace nlohmann { /// convention is followed. /// /// @tparam parameters_t The track parameters type -template +template struct adl_serializer { /// Covariance matrix type attached to the parameters using CovarianceMatrix = typename parameters_t::CovarianceMatrix; @@ -101,7 +86,7 @@ struct adl_serializer { // Bound track parameters have // reference surface attached // and position takes a geometry context - if constexpr (IsGenericBound) { + if constexpr (Acts::detail::isGenericBoundTrackParams) { Acts::GeometryContext gctx; j["position"] = t.fourPosition(gctx); @@ -152,7 +137,7 @@ struct adl_serializer { // reference surface attached // and constructor is hidden // behind a factory method - if constexpr (IsGenericBound) { + if constexpr (Acts::detail::isGenericBoundTrackParams) { Acts::GeometryContext gctx; auto referenceSurface = Acts::SurfaceJsonConverter::fromJson(j.at("referenceSurface")); @@ -178,7 +163,7 @@ struct adl_serializer { /// convention is followed. /// /// @tparam parameters_t The track parameters type -template +template struct adl_serializer> { using CovarianceMatrix = typename parameters_t::CovarianceMatrix; static void to_json(nlohmann::json& j, @@ -202,7 +187,7 @@ struct adl_serializer> { /// convention is followed. /// /// @tparam parameters_t The track parameters type -template +template struct adl_serializer> { using CovarianceMatrix = typename parameters_t::CovarianceMatrix; static void to_json(nlohmann::json& j, diff --git a/Tests/UnitTests/Core/TrackFinding/CMakeLists.txt b/Tests/UnitTests/Core/TrackFinding/CMakeLists.txt index 523200299ac..bf0c520d672 100644 --- a/Tests/UnitTests/Core/TrackFinding/CMakeLists.txt +++ b/Tests/UnitTests/Core/TrackFinding/CMakeLists.txt @@ -1,2 +1,3 @@ add_unittest(CombinatorialKalmanFilter CombinatorialKalmanFilterTests.cpp) add_unittest(TrackSelector TrackSelectorTests.cpp) +add_unittest(TrackParamsLookupAccumulator TrackParamsLookupAccumulatorTests.cpp) diff --git a/Tests/UnitTests/Core/TrackFinding/TrackParamsLookupAccumulatorTests.cpp b/Tests/UnitTests/Core/TrackFinding/TrackParamsLookupAccumulatorTests.cpp new file mode 100644 index 00000000000..10e12747fce --- /dev/null +++ b/Tests/UnitTests/Core/TrackFinding/TrackParamsLookupAccumulatorTests.cpp @@ -0,0 +1,221 @@ +// 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 +#include +#include + +#include "Acts/Definitions/Algebra.hpp" +#include "Acts/EventData/ParticleHypothesis.hpp" +#include "Acts/EventData/TrackParameters.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Surfaces/PlaneSurface.hpp" +#include "Acts/Surfaces/RectangleBounds.hpp" +#include "Acts/Surfaces/Surface.hpp" +#include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" +#include "Acts/TrackFinding/TrackParamsLookupAccumulator.hpp" +#include "Acts/Utilities/AxisFwd.hpp" +#include "Acts/Utilities/Grid.hpp" +#include "Acts/Utilities/GridAxisGenerators.hpp" + +#include +#include +#include +#include +#include +#include + +BOOST_AUTO_TEST_SUITE(TrackParamsLookupAccumulator) + +Acts::GeometryContext gctx; + +using Axis = + Acts::Axis; +using AxisGen = Acts::GridAxisGenerators::EqOpenEqOpen; + +using CellBound = std::pair, + std::shared_ptr>; + +using GridBound = Acts::Grid; +using AccBound = Acts::TrackParamsLookupAccumulator; + +using CellCurvilinear = + std::pair, + std::shared_ptr>; + +using GridCurvilinear = Acts::Grid; +using AccCurvilinear = Acts::TrackParamsLookupAccumulator; + +using CellFree = std::pair, + std::shared_ptr>; + +using GridFree = Acts::Grid; +using AccFree = Acts::TrackParamsLookupAccumulator; + +AxisGen axisGen{{-1, 1}, 2, {-1, 1}, 2}; + +BOOST_AUTO_TEST_CASE(Exceptions) { + // Instantiate grid + GridBound grid(axisGen()); + AccBound acc(grid); + + // Create a reference surface for bound parameters + auto transform = Acts::Transform3::Identity(); + auto bounds1 = std::make_shared(1, 1); + auto bounds2 = std::make_shared(2, 2); + + auto surf1 = + Acts::Surface::makeShared(transform, bounds1); + + auto surf2 = + Acts::Surface::makeShared(transform, bounds2); + + // Create parameters to accumulate + Acts::Vector4 pos{1, 2, 0, 4}; + Acts::Vector3 dir{1, 0, 0}; + Acts::ActsScalar P = 1; + + auto hypothesis1 = Acts::ParticleHypothesis::electron(); + auto hypothesis2 = Acts::ParticleHypothesis::muon(); + + auto pars1 = Acts::BoundTrackParameters::create(surf1, gctx, pos, dir, 1. / P, + std::nullopt, hypothesis1) + .value(); + + auto pars2 = Acts::BoundTrackParameters::create(surf2, gctx, pos, dir, 1. / P, + std::nullopt, hypothesis1) + .value(); + + auto pars3 = Acts::BoundTrackParameters::create(surf1, gctx, pos, dir, 1. / P, + std::nullopt, hypothesis2) + .value(); + + auto pars4 = Acts::BoundTrackParameters::create( + surf1, gctx, pos, dir, -1. / P, std::nullopt, hypothesis2) + .value(); + + // Get the point of the grid + auto bin = grid.localBinsFromGlobalBin(2); + auto center = grid.binCenter(bin); + Acts::Vector2 loc{center.at(0), center.at(1)}; + + // Fill in grid + acc.addTrack(pars1, pars1, loc); + + // Different reference surfaces + BOOST_CHECK_THROW(acc.addTrack(pars2, pars2, loc), std::invalid_argument); + + // Different particle hypotheses + BOOST_CHECK_THROW(acc.addTrack(pars3, pars3, loc), std::invalid_argument); + + // Different charges + BOOST_CHECK_THROW(acc.addTrack(pars4, pars4, loc), std::invalid_argument); +} + +BOOST_AUTO_TEST_CASE(Accumulation) { + // Instantiate grids + GridBound gridBound(axisGen()); + AccBound accBound(gridBound); + + GridCurvilinear gridCurvilinear(axisGen()); + AccCurvilinear accCurvilinear(gridCurvilinear); + + GridFree gridFree(axisGen()); + AccFree accFree(gridFree); + + // Create a reference surface for bound parameters + auto transform = Acts::Transform3::Identity(); + auto bounds = std::make_shared(1, 1); + auto surf = Acts::Surface::makeShared(transform, bounds); + + auto hypothesis = Acts::ParticleHypothesis::electron(); + + std::vector avgPoss; + std::vector avgMoms; + Acts::Vector4 pos{1, 2, 0, 4}; + for (std::size_t i = 0; i < gridBound.size(); i++) { + // Create parameters to accumulate + std::array fourPositions = {pos * (i + 1), pos * (i + 2), + pos * (i + 3), pos * (i + 4)}; + + std::array thetas = { + std::numbers::pi / (i + 1), std::numbers::pi / (i + 2), + std::numbers::pi / (i + 3), std::numbers::pi / (i + 4)}; + + std::array phis = { + 2 * std::numbers::pi / (i + 1), 2 * std::numbers::pi / (i + 2), + 2 * std::numbers::pi / (i + 3), 2 * std::numbers::pi / (i + 4)}; + + Acts::ActsScalar P = 1.5 * (i + 1); + + // Get the point of the grid + auto bin = gridBound.localBinsFromGlobalBin(i); + auto center = gridBound.binCenter(bin); + Acts::Vector2 loc{center.at(0), center.at(1)}; + + // Accumulate + Acts::Vector4 avgPos{0, 0, 0, 0}; + Acts::Vector3 avgMom{0, 0, 0}; + for (std::size_t j = 0; j < 4; j++) { + Acts::Vector3 direction{std::sin(thetas.at(j)) * std::cos(phis.at(j)), + std::sin(thetas.at(j)) * std::sin(phis.at(j)), + std::cos(thetas.at(j))}; + + avgPos += fourPositions.at(j); + avgMom += P * direction; + + // Fill in each grid + auto parsBound = Acts::BoundTrackParameters::create( + surf, gctx, fourPositions.at(j), direction, 1. / P, + std::nullopt, hypothesis) + .value(); + + auto parsCurvilinear = Acts::CurvilinearTrackParameters( + fourPositions.at(j), direction, 1. / P, std::nullopt, hypothesis); + + auto parsFree = Acts::FreeTrackParameters( + fourPositions.at(j), direction, 1. / P, std::nullopt, hypothesis); + + accBound.addTrack(parsBound, parsBound, loc); + accCurvilinear.addTrack(parsCurvilinear, parsCurvilinear, loc); + accFree.addTrack(parsFree, parsFree, loc); + } + avgPoss.push_back(avgPos / fourPositions.size()); + avgMoms.push_back(avgMom / fourPositions.size()); + } + + // Finalize and compare + GridBound avgGridBound = accBound.finalizeLookup(); + GridCurvilinear avgGridCurvilinear = accCurvilinear.finalizeLookup(); + GridFree avgGridFree = accFree.finalizeLookup(); + for (std::size_t i = 0; i < avgGridBound.size(); i++) { + auto [ipBound, refBound] = avgGridBound.at(i); + auto [ipCurvilinear, refCurvilinear] = avgGridCurvilinear.at(i); + auto [ipFree, refFree] = avgGridFree.at(i); + + Acts::Vector4 avgPos = avgPoss.at(i); + + Acts::Vector3 avgMom = avgMoms.at(i); + Acts::Vector3 avgDir = avgMom.normalized(); + Acts::ActsScalar avgP = avgMom.norm(); + + CHECK_CLOSE_ABS(ipBound->fourPosition(gctx), avgPos, 1e-3); + CHECK_CLOSE_ABS(ipBound->direction(), avgDir, 1e-3); + CHECK_CLOSE_ABS(ipBound->absoluteMomentum(), avgP, 1e-3); + + CHECK_CLOSE_ABS(ipCurvilinear->fourPosition(), avgPos, 1e-3); + CHECK_CLOSE_ABS(ipCurvilinear->direction(), avgDir, 1e-3); + CHECK_CLOSE_ABS(ipCurvilinear->absoluteMomentum(), avgP, 1e-3); + + CHECK_CLOSE_ABS(ipFree->fourPosition(), avgPos, 1e-3); + CHECK_CLOSE_ABS(ipFree->direction(), avgDir, 1e-3); + CHECK_CLOSE_ABS(ipFree->absoluteMomentum(), avgP, 1e-3); + } +} + +BOOST_AUTO_TEST_SUITE_END() From 5c3a8b81117927452c50c0947d2b47e6f76c1721 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Fri, 22 Nov 2024 08:31:15 +0100 Subject: [PATCH 3/8] refactor!: Deduplicate `estimateTrackParamsFromSeed` code (#3866) After a couple of iterations we can deduplicate the code with the free param estimation blocked by - https://github.com/acts-project/acts/pull/3835 - https://github.com/acts-project/acts/pull/3832 - https://github.com/acts-project/acts/pull/3863 --- .../Seeding/EstimateTrackParamsFromSeed.hpp | 172 ++++-------------- .../Seeding/EstimateTrackParamsFromSeed.cpp | 1 + .../src/TrackParamsEstimationAlgorithm.cpp | 16 +- .../src/PrototracksToParameters.cpp | 10 +- Examples/Python/tests/root_file_hashes.txt | 8 +- .../EstimateTrackParamsFromSeedTest.cpp | 9 +- 6 files changed, 55 insertions(+), 161 deletions(-) diff --git a/Core/include/Acts/Seeding/EstimateTrackParamsFromSeed.hpp b/Core/include/Acts/Seeding/EstimateTrackParamsFromSeed.hpp index c59a55ad533..e4618296b50 100644 --- a/Core/include/Acts/Seeding/EstimateTrackParamsFromSeed.hpp +++ b/Core/include/Acts/Seeding/EstimateTrackParamsFromSeed.hpp @@ -8,17 +8,14 @@ #pragma once +#include "Acts/Definitions/Algebra.hpp" #include "Acts/Definitions/TrackParametrization.hpp" #include "Acts/Definitions/Units.hpp" #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Surfaces/Surface.hpp" -#include "Acts/Utilities/Logger.hpp" -#include "Acts/Utilities/MathHelpers.hpp" #include "Acts/Utilities/Zip.hpp" #include -#include -#include #include #include @@ -27,17 +24,16 @@ namespace Acts { /// Estimate the full track parameters from three space points /// /// This method is based on the conformal map transformation. It estimates the -/// full free track parameters, i.e. (x, y, z, t, dx, dy, dz, q/p) at the -/// bottom space point. The bottom space is assumed to be the first element -/// in the range defined by the iterators. The magnetic field (which might be -/// along any direction) is also necessary for the momentum estimation. +/// full free track parameters, i.e. (x, y, z, t, dx, dy, dz, q/p) at the bottom +/// space point. The bottom space is assumed to be the first element in the +/// range defined by the iterators. The magnetic field (which might be along any +/// direction) is also necessary for the momentum estimation. /// /// This is a purely spatial estimation, i.e. the time parameter will be set to /// 0. /// -/// It resembles the method used in ATLAS for the track parameters -/// estimated from seed, i.e. the function InDet::SiTrackMaker_xk::getAtaPlane -/// here: +/// It resembles the method used in ATLAS for the track parameters estimated +/// from seed, i.e. the function InDet::SiTrackMaker_xk::getAtaPlane here: /// https://acode-browser.usatlas.bnl.gov/lxr/source/athena/InnerDetector/InDetRecTools/SiTrackMakerTool_xk/src/SiTrackMaker_xk.cxx /// /// @tparam spacepoint_iterator_t The type of space point iterator @@ -55,14 +51,13 @@ FreeVector estimateTrackParamsFromSeed(const Vector3& sp0, const Vector3& sp1, /// Estimate the full track parameters from three space points /// /// This method is based on the conformal map transformation. It estimates the -/// full free track parameters, i.e. (x, y, z, t, dx, dy, dz, q/p) at the -/// bottom space point. The bottom space is assumed to be the first element -/// in the range defined by the iterators. The magnetic field (which might be -/// along any direction) is also necessary for the momentum estimation. +/// full free track parameters, i.e. (x, y, z, t, dx, dy, dz, q/p) at the bottom +/// space point. The bottom space is assumed to be the first element in the +/// range defined by the iterators. The magnetic field (which might be along any +/// direction) is also necessary for the momentum estimation. /// -/// It resembles the method used in ATLAS for the track parameters -/// estimated from seed, i.e. the function InDet::SiTrackMaker_xk::getAtaPlane -/// here: +/// It resembles the method used in ATLAS for the track parameters estimated +/// from seed, i.e. the function InDet::SiTrackMaker_xk::getAtaPlane here: /// https://acode-browser.usatlas.bnl.gov/lxr/source/athena/InnerDetector/InDetRecTools/SiTrackMakerTool_xk/src/SiTrackMaker_xk.cxx /// /// @tparam spacepoint_iterator_t The type of space point iterator @@ -107,150 +102,53 @@ FreeVector estimateTrackParamsFromSeed(spacepoint_range_t spRange, /// This method is based on the conformal map transformation. It estimates the /// full bound track parameters, i.e. (loc0, loc1, phi, theta, q/p, t) at the /// bottom space point. The bottom space is assumed to be the first element -/// in the range defined by the iterators. It must lie on the surface -/// provided for the representation of the bound track parameters. The magnetic -/// field (which might be along any direction) is also necessary for the -/// momentum estimation. +/// in the range defined by the iterators. It must lie on the surface provided +/// for the representation of the bound track parameters. The magnetic field +/// (which might be along any direction) is also necessary for the momentum +/// estimation. /// -/// It resembles the method used in ATLAS for the track parameters -/// estimated from seed, i.e. the function InDet::SiTrackMaker_xk::getAtaPlane -/// here: +/// It resembles the method used in ATLAS for the track parameters estimated +/// from seed, i.e. the function InDet::SiTrackMaker_xk::getAtaPlane here: /// https://acode-browser.usatlas.bnl.gov/lxr/source/athena/InnerDetector/InDetRecTools/SiTrackMakerTool_xk/src/SiTrackMaker_xk.cxx /// /// @tparam spacepoint_iterator_t The type of space point iterator /// /// @param gctx is the geometry context -/// @param spBegin is the begin iterator for the space points -/// @param spEnd is the end iterator for the space points +/// @param spRange is the range of space points /// @param surface is the surface of the bottom space point. The estimated bound /// track parameters will be represented also at this surface /// @param bField is the magnetic field vector -/// @param logger A logger instance /// -/// @return optional bound parameters -template -std::optional estimateTrackParamsFromSeed( - const GeometryContext& gctx, spacepoint_iterator_t spBegin, - spacepoint_iterator_t spEnd, const Surface& surface, const Vector3& bField, - const Acts::Logger& logger = getDummyLogger()) { - // Check the number of provided space points - std::size_t numSP = std::distance(spBegin, spEnd); - if (numSP != 3) { - ACTS_ERROR("There should be exactly three space points provided."); - return std::nullopt; - } - - // The global positions of the bottom, middle and space points - std::array spGlobalPositions = {Vector3::Zero(), Vector3::Zero(), - Vector3::Zero()}; - std::array, 3> spGlobalTimes = { - std::nullopt, std::nullopt, std::nullopt}; - // The first, second and third space point are assumed to be bottom, middle - // and top space point, respectively - for (std::size_t isp = 0; isp < 3; ++isp) { - spacepoint_iterator_t it = std::next(spBegin, isp); - if (*it == nullptr) { - ACTS_ERROR("Empty space point found. This should not happen."); - return std::nullopt; - } - const auto& sp = *it; - spGlobalPositions[isp] = Vector3(sp->x(), sp->y(), sp->z()); - spGlobalTimes[isp] = sp->t(); - } - - // Define a new coordinate frame with its origin at the bottom space point, z - // axis long the magnetic field direction and y axis perpendicular to vector - // from the bottom to middle space point. Hence, the projection of the middle - // space point on the transverse plane will be located at the x axis of the - // new frame. - Vector3 relVec = spGlobalPositions[1] - spGlobalPositions[0]; - Vector3 newZAxis = bField.normalized(); - Vector3 newYAxis = newZAxis.cross(relVec).normalized(); - Vector3 newXAxis = newYAxis.cross(newZAxis); - RotationMatrix3 rotation; - rotation.col(0) = newXAxis; - rotation.col(1) = newYAxis; - rotation.col(2) = newZAxis; - // The center of the new frame is at the bottom space point - Translation3 trans(spGlobalPositions[0]); - // The transform which constructs the new frame - Transform3 transform(trans * rotation); - - // The coordinate of the middle and top space point in the new frame - Vector3 local1 = transform.inverse() * spGlobalPositions[1]; - Vector3 local2 = transform.inverse() * spGlobalPositions[2]; - - // In the new frame the bottom sp is at the origin, while the middle - // sp in along the x axis. As such, the x-coordinate of the circle is - // at: x-middle / 2. - // The y coordinate can be found by using the straight line passing - // between the mid point between the middle and top sp and perpendicular to - // the line connecting them - Vector2 circleCenter; - circleCenter(0) = 0.5 * local1(0); +/// @return bound parameters +template +Result estimateTrackParamsFromSeed(const GeometryContext& gctx, + spacepoint_range_t spRange, + const Surface& surface, + const Vector3& bField) { + FreeVector freeParams = estimateTrackParamsFromSeed(spRange, bField); - ActsScalar deltaX21 = local2(0) - local1(0); - ActsScalar sumX21 = local2(0) + local1(0); - // straight line connecting the two points - // y = a * x + c (we don't care about c right now) - // we simply need the slope - // we compute 1./a since this is what we need for the following computation - ActsScalar ia = deltaX21 / local2(1); - // Perpendicular line is then y = -1/a *x + b - // we can evaluate b given we know a already by imposing - // the line passes through P = (0.5 * (x2 + x1), 0.5 * y2) - ActsScalar b = 0.5 * (local2(1) + ia * sumX21); - circleCenter(1) = -ia * circleCenter(0) + b; - // Radius is a signed distance between circleCenter and first sp, which is at - // (0, 0) in the new frame. Sign depends on the slope a (positive vs negative) - int sign = ia > 0 ? -1 : 1; - const ActsScalar R = circleCenter.norm(); - ActsScalar invTanTheta = - local2.z() / (2 * R * std::asin(local2.head<2>().norm() / (2 * R))); - // The momentum direction in the new frame (the center of the circle has the - // coordinate (-1.*A/(2*B), 1./(2*B))) - ActsScalar A = -circleCenter(0) / circleCenter(1); - Vector3 transDirection(1., A, fastHypot(1, A) * invTanTheta); - // Transform it back to the original frame - Vector3 direction = rotation * transDirection.normalized(); + const auto* sp0 = *spRange.begin(); + Vector3 origin = Vector3(sp0->x(), sp0->y(), sp0->z()); + Vector3 direction = freeParams.segment<3>(eFreeDir0); - // Initialize the bound parameters vector BoundVector params = BoundVector::Zero(); - - // The estimated phi and theta params[eBoundPhi] = VectorHelpers::phi(direction); params[eBoundTheta] = VectorHelpers::theta(direction); + params[eBoundQOverP] = freeParams[eFreeQOverP]; // Transform the bottom space point to local coordinates of the provided // surface - auto lpResult = surface.globalToLocal(gctx, spGlobalPositions[0], direction); + auto lpResult = surface.globalToLocal(gctx, origin, direction); if (!lpResult.ok()) { - ACTS_ERROR( - "Global to local transformation did not succeed. Please make sure the " - "bottom space point lies on the provided surface."); - return std::nullopt; + return Result::failure(lpResult.error()); } Vector2 bottomLocalPos = lpResult.value(); // The estimated loc0 and loc1 params[eBoundLoc0] = bottomLocalPos.x(); params[eBoundLoc1] = bottomLocalPos.y(); - params[eBoundTime] = spGlobalTimes[0].value_or(0.); - - ActsScalar bFieldStrength = bField.norm(); - // The estimated q/pt in [GeV/c]^-1 (note that the pt is the projection of - // momentum on the transverse plane of the new frame) - ActsScalar qOverPt = sign / (bFieldStrength * R); - // The estimated q/p in [GeV/c]^-1 - params[eBoundQOverP] = qOverPt / fastHypot(1., invTanTheta); + params[eBoundTime] = sp0->t().value_or(0); - if (params.hasNaN()) { - ACTS_ERROR( - "The NaN value exists at the estimated track parameters from seed with" - << "\nbottom sp: " << spGlobalPositions[0] << "\nmiddle sp: " - << spGlobalPositions[1] << "\ntop sp: " << spGlobalPositions[2]); - return std::nullopt; - } - return params; + return Result::success(params); } /// Configuration for the estimation of the covariance matrix of the track diff --git a/Core/src/Seeding/EstimateTrackParamsFromSeed.cpp b/Core/src/Seeding/EstimateTrackParamsFromSeed.cpp index 055691bbb2f..b071d5dd7e6 100644 --- a/Core/src/Seeding/EstimateTrackParamsFromSeed.cpp +++ b/Core/src/Seeding/EstimateTrackParamsFromSeed.cpp @@ -9,6 +9,7 @@ #include "Acts/Seeding/EstimateTrackParamsFromSeed.hpp" #include "Acts/Definitions/TrackParametrization.hpp" +#include "Acts/Utilities/MathHelpers.hpp" #include diff --git a/Examples/Algorithms/TrackFinding/src/TrackParamsEstimationAlgorithm.cpp b/Examples/Algorithms/TrackFinding/src/TrackParamsEstimationAlgorithm.cpp index dfb0269a56d..f2711ce1d1a 100644 --- a/Examples/Algorithms/TrackFinding/src/TrackParamsEstimationAlgorithm.cpp +++ b/Examples/Algorithms/TrackFinding/src/TrackParamsEstimationAlgorithm.cpp @@ -21,12 +21,10 @@ #include "ActsExamples/EventData/Track.hpp" #include "ActsExamples/Framework/AlgorithmContext.hpp" -#include #include #include #include #include -#include #include #include @@ -119,16 +117,14 @@ ProcessCode TrackParamsEstimationAlgorithm::execute( } // Estimate the track parameters from seed - auto optParams = Acts::estimateTrackParamsFromSeed( - ctx.geoContext, seed.sp().begin(), seed.sp().end(), *surface, field, - logger()); - if (!optParams.has_value()) { - ACTS_WARNING("Estimation of track parameters for seed " << iseed - << " failed."); + const auto paramsResult = Acts::estimateTrackParamsFromSeed( + ctx.geoContext, seed.sp(), *surface, field); + if (!paramsResult.ok()) { + ACTS_WARNING("Skip track because param estimation failed " + << paramsResult.error()); continue; } - - const auto& params = optParams.value(); + const auto& params = *paramsResult; Acts::EstimateTrackParamCovarianceConfig config{ .initialSigmas = diff --git a/Examples/Algorithms/TrackFindingExaTrkX/src/PrototracksToParameters.cpp b/Examples/Algorithms/TrackFindingExaTrkX/src/PrototracksToParameters.cpp index 9ffe49ae460..53fe1cdbdad 100644 --- a/Examples/Algorithms/TrackFindingExaTrkX/src/PrototracksToParameters.cpp +++ b/Examples/Algorithms/TrackFindingExaTrkX/src/PrototracksToParameters.cpp @@ -167,17 +167,17 @@ ProcessCode PrototracksToParameters::execute( continue; } - auto pars = Acts::estimateTrackParamsFromSeed( - ctx.geoContext, seed.sp().begin(), seed.sp().end(), surface, field); - - if (not pars) { + auto parsResult = Acts::estimateTrackParamsFromSeed( + ctx.geoContext, seed.sp(), surface, field); + if (!parsResult.ok()) { ACTS_WARNING("Skip track because of bad params"); } + const auto &pars = *parsResult; seededTracks.push_back(track); seeds.emplace_back(std::move(seed)); parameters.push_back(Acts::BoundTrackParameters( - surface.getSharedPtr(), *pars, m_covariance, m_cfg.particleHypothesis)); + surface.getSharedPtr(), pars, m_covariance, m_cfg.particleHypothesis)); } if (skippedTracks > 0) { diff --git a/Examples/Python/tests/root_file_hashes.txt b/Examples/Python/tests/root_file_hashes.txt index 45337b2f762..4674ce1ce2e 100644 --- a/Examples/Python/tests/root_file_hashes.txt +++ b/Examples/Python/tests/root_file_hashes.txt @@ -41,11 +41,11 @@ test_ckf_tracks_example[generic-truth_estimated]__tracksummary_ckf.root: 8e0116c test_ckf_tracks_example[generic-truth_estimated]__performance_seeding.root: 1facb05c066221f6361b61f015cdf0918e94d9f3fce2269ec7b6a4dffeb2bc7e test_ckf_tracks_example[generic-truth_smeared]__trackstates_ckf.root: 82a6744980553e6274df78eea15f0dec22676b1c04e14afc3828bff9bbf5e1b1 test_ckf_tracks_example[generic-truth_smeared]__tracksummary_ckf.root: 06d6ae1d05cb611b19df3c59531997c9b0108f5ef6027d76c4827bd2d9edb921 -test_ckf_tracks_example[odd-full_seeding]__trackstates_ckf.root: 17c48c5a61b1a5495d91336cdf06f9c24e50d81349c1f31d7c70ffff5810a376 -test_ckf_tracks_example[odd-full_seeding]__tracksummary_ckf.root: b5805e54030ab8ac80a8c0a764700c65433dc659783fc8ff3b2c96e512a1d045 +test_ckf_tracks_example[odd-full_seeding]__trackstates_ckf.root: 53a96c225ed78bd7da1491ae3ff4173f0e6c8bffe27e3eab1ab7adfe55426080 +test_ckf_tracks_example[odd-full_seeding]__tracksummary_ckf.root: 2a98d8ec8fae97e18f4661580b71885f558d7222f94bca5edfbf5cdb595021f7 test_ckf_tracks_example[odd-full_seeding]__performance_seeding_trees.root: 43c58577aafe07645e5660c4f43904efadf91d8cda45c5c04c248bbe0f59814f -test_ckf_tracks_example[odd-truth_estimated]__trackstates_ckf.root: 86be5a086d2a87dfde9320bb880bd0788d733ea9727cb5ee6dc0282ec4be39f4 -test_ckf_tracks_example[odd-truth_estimated]__tracksummary_ckf.root: ffce6a73f16986cb3f0386d4a8c1e0ff6f0b4130b9bb12d1af0eb905d000e3e9 +test_ckf_tracks_example[odd-truth_estimated]__trackstates_ckf.root: 7ec5f4b24fa69bfc9d812a6f224d74d36df2d0a42aef791ae0116f309d6f1433 +test_ckf_tracks_example[odd-truth_estimated]__tracksummary_ckf.root: 1eaae038ced2cc5c757480ca42eab60cdaff14d812c34a807a841267d6bfa110 test_ckf_tracks_example[odd-truth_estimated]__performance_seeding.root: 1a36b7017e59f1c08602ef3c2cb0483c51df248f112e3780c66594110719c575 test_ckf_tracks_example[odd-truth_smeared]__trackstates_ckf.root: 35a65e15a6f479f628a96f56ee78e1ac371d71a686ee0c974944d681499fe6bd test_ckf_tracks_example[odd-truth_smeared]__tracksummary_ckf.root: 3e257de624674fa9a19dcc72598c78c29a52633821acaa56dc2aa39a1395f1b5 diff --git a/Tests/UnitTests/Core/Seeding/EstimateTrackParamsFromSeedTest.cpp b/Tests/UnitTests/Core/Seeding/EstimateTrackParamsFromSeedTest.cpp index 9aab6c1c70b..45dbbd9d0bb 100644 --- a/Tests/UnitTests/Core/Seeding/EstimateTrackParamsFromSeedTest.cpp +++ b/Tests/UnitTests/Core/Seeding/EstimateTrackParamsFromSeedTest.cpp @@ -174,11 +174,10 @@ BOOST_AUTO_TEST_CASE(trackparameters_estimation_test) { BOOST_CHECK(!estFreeParams.hasNaN()); // Test the bound track parameters estimator - auto fullParamsOpt = estimateTrackParamsFromSeed( - geoCtx, spacePointPtrs.begin(), spacePointPtrs.end(), - *bottomSurface, bField, *logger); - BOOST_REQUIRE(fullParamsOpt.has_value()); - const auto& estFullParams = fullParamsOpt.value(); + auto estFullParamsResult = estimateTrackParamsFromSeed( + geoCtx, spacePointPtrs, *bottomSurface, bField); + BOOST_CHECK(estFullParamsResult.ok()); + const auto& estFullParams = estFullParamsResult.value(); BOOST_TEST_INFO( "The estimated full track parameters at the bottom space point: " "\n" From c3c4bf5209ac59430e45a9cf0d2acf9cfde2d914 Mon Sep 17 00:00:00 2001 From: "Alexander J. Pfleger" <70842573+AJPfleger@users.noreply.github.com> Date: Fri, 22 Nov 2024 08:39:19 +0100 Subject: [PATCH 4/8] docs(sphinx): remove outdated warnings from ignore list (#3878) --- docs/known-warnings.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/known-warnings.txt b/docs/known-warnings.txt index fa1e28dcb70..2138dc11bb9 100644 --- a/docs/known-warnings.txt +++ b/docs/known-warnings.txt @@ -3,8 +3,6 @@ .*Duplicate C\+\+ declaration.* .*Duplicate ID: .* .*Duplicate explicit target name: .* -.*doxygenfile: Found multiple matches for file \"SeedFinder.hpp.* -.*Duplicate explicit target name: .*class_acts_1_1_axis_aligned_bounding_box_.* .*undefined label: .*class_acts_1_1_convex_polygon_bounds_3_01_polygon_dynamic_01_4.* .*undefined label: .*class_acts_1_1_grid_surface_material_t.* # I think these are because we use specialization From 6e3a9a683e66cb28169f15f8d8f6c8390e01651d Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 22 Nov 2024 12:19:39 +0100 Subject: [PATCH 5/8] refactor: Avoid `new`/`delete` in a number of places. (#3828) --- .../Acts/Geometry/SurfaceArrayCreator.hpp | 16 +++--- Core/include/Acts/Seeding/GbtsDataStorage.hpp | 55 +++++++------------ Core/include/Acts/Seeding/GbtsGeometry.hpp | 38 ++++--------- Core/include/Acts/Seeding/SeedFinderGbts.ipp | 28 ++++------ .../Acts/TrackFinding/GbtsConnector.hpp | 9 +-- Core/src/Geometry/LayerCreator.cpp | 3 +- Core/src/TrackFinding/GbtsConnector.cpp | 19 ++----- .../GenericDetector/ProtoLayerCreatorT.hpp | 15 +++-- .../MagneticField/src/FieldMapRootIo.cpp | 6 +- .../Io/Root/RootAthenaNTupleReader.hpp | 4 +- .../Io/Root/RootMaterialTrackReader.hpp | 2 +- .../Io/Root/RootParticleReader.hpp | 2 +- .../ActsExamples/Io/Root/RootSimHitReader.hpp | 4 +- .../Io/Root/RootTrackSummaryReader.hpp | 2 +- .../ActsExamples/Io/Root/RootVertexReader.hpp | 2 +- .../Io/Root/src/RootAthenaNTupleReader.cpp | 4 +- Examples/Io/Root/src/RootBFieldWriter.cpp | 7 +-- .../Io/Root/src/RootMaterialTrackReader.cpp | 4 +- Examples/Io/Root/src/RootParticleReader.cpp | 2 +- Examples/Io/Root/src/RootSimHitReader.cpp | 4 +- .../Io/Root/src/RootTrackSummaryReader.cpp | 2 +- Examples/Io/Root/src/RootVertexReader.cpp | 2 +- .../NuclearInteractionParametrisation.cpp | 13 +++-- 23 files changed, 100 insertions(+), 143 deletions(-) diff --git a/Core/include/Acts/Geometry/SurfaceArrayCreator.hpp b/Core/include/Acts/Geometry/SurfaceArrayCreator.hpp index 584e8ee6992..9906fda7939 100644 --- a/Core/include/Acts/Geometry/SurfaceArrayCreator.hpp +++ b/Core/include/Acts/Geometry/SurfaceArrayCreator.hpp @@ -381,8 +381,8 @@ class SurfaceArrayCreator { Axis axisB(pAxisB.min, pAxisB.max, pAxisB.nBins); using SGL = SurfaceArray::SurfaceGridLookup; - ptr = std::unique_ptr(static_cast( - new SGL(globalToLocal, localToGlobal, std::make_tuple(axisA, axisB), {pAxisA.bValue, pAxisB.bValue}))); + ptr = std::make_unique( + globalToLocal, localToGlobal, std::pair{axisA, axisB}, std::vector{pAxisA.bValue, pAxisB.bValue}); } else if (pAxisA.bType == equidistant && pAxisB.bType == arbitrary) { @@ -390,8 +390,8 @@ class SurfaceArrayCreator { Axis axisB(pAxisB.binEdges); using SGL = SurfaceArray::SurfaceGridLookup; - ptr = std::unique_ptr(static_cast( - new SGL(globalToLocal, localToGlobal, std::make_tuple(axisA, axisB), {pAxisA.bValue, pAxisB.bValue}))); + ptr = std::make_unique( + globalToLocal, localToGlobal, std::pair{axisA, axisB}, std::vector{pAxisA.bValue, pAxisB.bValue}); } else if (pAxisA.bType == arbitrary && pAxisB.bType == equidistant) { @@ -399,8 +399,8 @@ class SurfaceArrayCreator { Axis axisB(pAxisB.min, pAxisB.max, pAxisB.nBins); using SGL = SurfaceArray::SurfaceGridLookup; - ptr = std::unique_ptr(static_cast( - new SGL(globalToLocal, localToGlobal, std::make_tuple(axisA, axisB), {pAxisA.bValue, pAxisB.bValue}))); + ptr = std::make_unique( + globalToLocal, localToGlobal, std::pair{axisA, axisB}, std::vector{pAxisA.bValue, pAxisB.bValue}); } else /*if (pAxisA.bType == arbitrary && pAxisB.bType == arbitrary)*/ { @@ -408,8 +408,8 @@ class SurfaceArrayCreator { Axis axisB(pAxisB.binEdges); using SGL = SurfaceArray::SurfaceGridLookup; - ptr = std::unique_ptr(static_cast( - new SGL(globalToLocal, localToGlobal, std::make_tuple(axisA, axisB), {pAxisA.bValue, pAxisB.bValue}))); + ptr = std::make_unique( + globalToLocal, localToGlobal, std::pair{axisA, axisB}, std::vector{pAxisA.bValue, pAxisB.bValue}); } // clang-format on diff --git a/Core/include/Acts/Seeding/GbtsDataStorage.hpp b/Core/include/Acts/Seeding/GbtsDataStorage.hpp index c28b0cc2413..8c7ba861bcd 100644 --- a/Core/include/Acts/Seeding/GbtsDataStorage.hpp +++ b/Core/include/Acts/Seeding/GbtsDataStorage.hpp @@ -13,6 +13,7 @@ #include "Acts/Seeding/GbtsGeometry.hpp" #include +#include #include #include #include @@ -47,13 +48,6 @@ struct GbtsSP { template class GbtsNode { public: - struct CompareByPhi { - bool operator()(const GbtsNode *n1, - const GbtsNode *n2) { - return (n1->m_spGbts.phi() < n2->m_spGbts.phi()); - } - }; - GbtsNode(const GbtsSP &spGbts, float minT = -100.0, float maxT = 100.0) : m_spGbts(spGbts), m_minCutOnTau(minT), m_maxCutOnTau(maxT) {} @@ -97,27 +91,20 @@ class GbtsEtaBin { public: GbtsEtaBin() { m_vn.clear(); } - ~GbtsEtaBin() { - for (typename std::vector *>::iterator it = - m_vn.begin(); - it != m_vn.end(); ++it) { - delete (*it); - } - } - void sortByPhi() { - std::ranges::sort(m_vn, - typename Acts::GbtsNode::CompareByPhi()); + std::ranges::sort(m_vn, [](const auto &n1, const auto &n2) { + return (n1->m_spGbts.phi() < n2->m_spGbts.phi()); + }); } bool empty() const { return m_vn.empty(); } void generatePhiIndexing(float dphi) { for (unsigned int nIdx = 0; nIdx < m_vn.size(); nIdx++) { - GbtsNode *pN = m_vn.at(nIdx); + GbtsNode &pN = *m_vn.at(nIdx); // float phi = pN->m_sp.phi(); // float phi = (std::atan(pN->m_sp.x() / pN->m_sp.y())); - float phi = pN->m_spGbts.phi(); + float phi = pN.m_spGbts.phi(); if (phi <= std::numbers::pi_v - dphi) { continue; } @@ -127,14 +114,14 @@ class GbtsEtaBin { } for (unsigned int nIdx = 0; nIdx < m_vn.size(); nIdx++) { - GbtsNode *pN = m_vn.at(nIdx); - float phi = pN->m_spGbts.phi(); + GbtsNode &pN = *m_vn.at(nIdx); + float phi = pN.m_spGbts.phi(); m_vPhiNodes.push_back(std::pair(phi, nIdx)); } for (unsigned int nIdx = 0; nIdx < m_vn.size(); nIdx++) { - GbtsNode *pN = m_vn.at(nIdx); - float phi = pN->m_spGbts.phi(); + GbtsNode &pN = *m_vn.at(nIdx); + float phi = pN.m_spGbts.phi(); if (phi >= -std::numbers::pi_v + dphi) { break; } @@ -143,9 +130,7 @@ class GbtsEtaBin { } } - std::vector *> m_vn; - // TODO change to - // std::vector>> m_vn; + std::vector>> m_vn; std::vector> m_vPhiNodes; }; @@ -186,8 +171,9 @@ class GbtsDataStorage { 1.6 + 0.15 / (cluster_width + 0.2) + 6.1 * (cluster_width - 0.2); } - m_etaBins.at(binIndex).m_vn.push_back(new GbtsNode( - sp, min_tau, max_tau)); // adding ftf member to nodes + m_etaBins.at(binIndex).m_vn.push_back( + std::make_unique>( + sp, min_tau, max_tau)); // adding ftf member to nodes } else { if (useClusterWidth) { float cluster_width = 1; // temporary while cluster width not available @@ -195,7 +181,8 @@ class GbtsDataStorage { return -3; } } - m_etaBins.at(binIndex).m_vn.push_back(new GbtsNode(sp)); + m_etaBins.at(binIndex).m_vn.push_back( + std::make_unique>(sp)); } return 0; @@ -218,16 +205,14 @@ class GbtsDataStorage { vn.clear(); vn.reserve(numberOfNodes()); for (const auto &b : m_etaBins) { - for (typename std::vector *>::const_iterator nIt = - b.m_vn.begin(); - nIt != b.m_vn.end(); ++nIt) { - if ((*nIt)->m_in.empty()) { + for (const auto &n : b.m_vn) { + if (n->m_in.empty()) { continue; } - if ((*nIt)->m_out.empty()) { + if (n->m_out.empty()) { continue; } - vn.push_back(*nIt); + vn.push_back(n.get()); } } } diff --git a/Core/include/Acts/Seeding/GbtsGeometry.hpp b/Core/include/Acts/Seeding/GbtsGeometry.hpp index 54931b200b8..cc1af647d28 100644 --- a/Core/include/Acts/Seeding/GbtsGeometry.hpp +++ b/Core/include/Acts/Seeding/GbtsGeometry.hpp @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -277,15 +278,10 @@ class GbtsGeometry { // calculating bin tables in the connector... - for (std::map>::const_iterator it = - m_connector->m_connMap.begin(); - it != m_connector->m_connMap.end(); ++it) { - const std::vector &vConn = (*it).second; - - for (std::vector::const_iterator cIt = vConn.begin(); - cIt != vConn.end(); ++cIt) { - unsigned int src = (*cIt)->m_src; // n2 : the new connectors - unsigned int dst = (*cIt)->m_dst; // n1 + for (auto &[_, vConn] : m_connector->m_connMap) { + for (auto &c : vConn) { + unsigned int src = c->m_src; // n2 : the new connectors + unsigned int dst = c->m_dst; // n1 const GbtsLayer *pL1 = getGbtsLayerByKey(dst); const GbtsLayer *pL2 = getGbtsLayerByKey(src); @@ -301,7 +297,7 @@ class GbtsGeometry { int nSrcBins = pL2->m_bins.size(); int nDstBins = pL1->m_bins.size(); - (*cIt)->m_binTable.resize(nSrcBins * nDstBins, 0); + c->m_binTable.resize(nSrcBins * nDstBins, 0); for (int b1 = 0; b1 < nDstBins; b1++) { // loop over bins in Layer 1 for (int b2 = 0; b2 < nSrcBins; b2++) { // loop over bins in Layer 2 @@ -309,7 +305,7 @@ class GbtsGeometry { continue; } int address = b1 + b2 * nDstBins; - (*cIt)->m_binTable.at(address) = 1; + c->m_binTable.at(address) = 1; } } } @@ -322,17 +318,6 @@ class GbtsGeometry { GbtsGeometry(const GbtsGeometry &) = delete; GbtsGeometry &operator=(const GbtsGeometry &) = delete; - ~GbtsGeometry() { - for (typename std::vector *>::iterator it = - m_layArray.begin(); - it != m_layArray.end(); ++it) { - delete (*it); - } - - m_layMap.clear(); - m_layArray.clear(); - } - const GbtsLayer *getGbtsLayerByKey(unsigned int key) const { typename std::map *>::const_iterator it = m_layMap.find(key); @@ -344,7 +329,7 @@ class GbtsGeometry { } const GbtsLayer *getGbtsLayerByIndex(int idx) const { - return m_layArray.at(idx); + return m_layArray.at(idx).get(); } int num_bins() const { return m_nEtaBins; } @@ -357,18 +342,19 @@ class GbtsGeometry { unsigned int layerKey = l.m_subdet; // this should be combined ID float ew = m_etaBinWidth; - GbtsLayer *pHL = new GbtsLayer(l, ew, bin0); + auto upHL = std::make_unique>(l, ew, bin0); + auto *pHL = upHL.get(); m_layMap.insert( std::pair *>(layerKey, pHL)); - m_layArray.push_back(pHL); + m_layArray.push_back(std::move(upHL)); return pHL; } float m_etaBinWidth{}; std::map *> m_layMap; - std::vector *> m_layArray; + std::vector>> m_layArray; int m_nEtaBins{0}; diff --git a/Core/include/Acts/Seeding/SeedFinderGbts.ipp b/Core/include/Acts/Seeding/SeedFinderGbts.ipp index ed2fe157acf..fb2722db616 100644 --- a/Core/include/Acts/Seeding/SeedFinderGbts.ipp +++ b/Core/include/Acts/Seeding/SeedFinderGbts.ipp @@ -160,12 +160,7 @@ void SeedFinderGbts::runGbts_TrackFinder( } unsigned int first_it = 0; - for (typename std::vector< - GbtsNode*>::const_iterator n1It = - B1.m_vn.begin(); - n1It != B1.m_vn.end(); ++n1It) { // loop over nodes in Layer 1 - - GbtsNode* n1 = (*n1It); + for (const auto& n1 : B1.m_vn) { // loop over nodes in Layer 1 if (n1->m_in.size() >= MAX_SEG_PER_NODE) { continue; @@ -195,7 +190,7 @@ void SeedFinderGbts::runGbts_TrackFinder( } GbtsNode* n2 = - B2.m_vn.at(B2.m_vPhiNodes.at(n2PhiIdx).second); + B2.m_vn.at(B2.m_vPhiNodes.at(n2PhiIdx).second).get(); if (n2->m_out.size() >= MAX_SEG_PER_NODE) { continue; @@ -304,8 +299,8 @@ void SeedFinderGbts::runGbts_TrackFinder( float dPhi1 = std::asin(curv * r1); if (nEdges < m_config.MaxEdges) { - edgeStorage.emplace_back(n1, n2, exp_eta, curv, phi1 + dPhi1, - phi2 + dPhi2); + edgeStorage.emplace_back(n1.get(), n2, exp_eta, curv, + phi1 + dPhi1, phi2 + dPhi2); n1->addIn(nEdges); n2->addOut(nEdges); @@ -332,21 +327,20 @@ void SeedFinderGbts::runGbts_TrackFinder( int nNodes = vNodes.size(); for (int nodeIdx = 0; nodeIdx < nNodes; nodeIdx++) { - const GbtsNode* pN = vNodes.at(nodeIdx); + const GbtsNode& pN = *vNodes.at(nodeIdx); std::vector> in_sort, out_sort; - in_sort.resize(pN->m_in.size()); - out_sort.resize(pN->m_out.size()); + in_sort.resize(pN.m_in.size()); + out_sort.resize(pN.m_out.size()); - for (int inIdx = 0; inIdx < static_cast(pN->m_in.size()); inIdx++) { - int inEdgeIdx = pN->m_in.at(inIdx); + for (int inIdx = 0; inIdx < static_cast(pN.m_in.size()); inIdx++) { + int inEdgeIdx = pN.m_in.at(inIdx); Acts::GbtsEdge* pS = &(edgeStorage.at(inEdgeIdx)); in_sort[inIdx].second = inEdgeIdx; in_sort[inIdx].first = pS->m_p[0]; } - for (int outIdx = 0; outIdx < static_cast(pN->m_out.size()); - outIdx++) { - int outEdgeIdx = pN->m_out.at(outIdx); + for (int outIdx = 0; outIdx < static_cast(pN.m_out.size()); outIdx++) { + int outEdgeIdx = pN.m_out.at(outIdx); Acts::GbtsEdge* pS = &(edgeStorage.at(outEdgeIdx)); out_sort[outIdx].second = outEdgeIdx; out_sort[outIdx].first = pS->m_p[0]; diff --git a/Core/include/Acts/TrackFinding/GbtsConnector.hpp b/Core/include/Acts/TrackFinding/GbtsConnector.hpp index f4cddd2527b..d4724929ac2 100644 --- a/Core/include/Acts/TrackFinding/GbtsConnector.hpp +++ b/Core/include/Acts/TrackFinding/GbtsConnector.hpp @@ -11,8 +11,8 @@ // TODO: update to C++17 style // Consider to moving to detail subdirectory #include -#include #include +#include #include namespace Acts { @@ -39,15 +39,10 @@ class GbtsConnector { GbtsConnector(std::ifstream &inFile); - ~GbtsConnector(); - float m_etaBin{}; std::map> m_layerGroups; - std::map> m_connMap; - // TODO: change to std::map > - // m_connMap; or std::map> > m_connMap; + std::map>> m_connMap; }; } // namespace Acts diff --git a/Core/src/Geometry/LayerCreator.cpp b/Core/src/Geometry/LayerCreator.cpp index 632274c671f..e24ff8e0661 100644 --- a/Core/src/Geometry/LayerCreator.cpp +++ b/Core/src/Geometry/LayerCreator.cpp @@ -407,8 +407,7 @@ Acts::MutableLayerPtr Acts::LayerCreator::planeLayer( } // create the layer and push it back - std::shared_ptr pBounds( - new RectangleBounds(layerHalf1, layerHalf2)); + auto pBounds = std::make_shared(layerHalf1, layerHalf2); // create the layer MutableLayerPtr pLayer = diff --git a/Core/src/TrackFinding/GbtsConnector.cpp b/Core/src/TrackFinding/GbtsConnector.cpp index d947894871c..69e0f7919e5 100644 --- a/Core/src/TrackFinding/GbtsConnector.cpp +++ b/Core/src/TrackFinding/GbtsConnector.cpp @@ -9,7 +9,6 @@ // TODO: update to C++17 style #include "Acts/TrackFinding/GbtsConnector.hpp" -#include #include #include #include @@ -34,7 +33,7 @@ GbtsConnector::GbtsConnector(std::ifstream &inFile) { inFile >> lIdx >> stage >> src >> dst >> height >> width >> nEntries; - GbtsConnection *pC = new GbtsConnection(src, dst); + auto pC = std::make_unique(src, dst); int dummy{}; @@ -47,19 +46,17 @@ GbtsConnector::GbtsConnector(std::ifstream &inFile) { int vol_id = src / 1000; if (vol_id == 13 || vol_id == 12 || vol_id == 14) { - delete pC; continue; } vol_id = dst / 1000; if (vol_id == 13 || vol_id == 12 || vol_id == 14) { - delete pC; continue; } auto &connections = m_connMap[stage]; - connections.push_back(pC); + connections.push_back(std::move(pC)); } // re-arrange the connection stages @@ -69,7 +66,9 @@ GbtsConnector::GbtsConnector(std::ifstream &inFile) { std::map> newConnMap; for (const auto &[_, value] : m_connMap) { - std::ranges::copy(value, std::back_inserter(lConns)); + for (const auto &conn : value) { + lConns.push_back(conn.get()); + } } int stageCounter = 0; @@ -172,12 +171,4 @@ GbtsConnector::GbtsConnector(std::ifstream &inFile) { newConnMap.clear(); } -GbtsConnector::~GbtsConnector() { - m_layerGroups.clear(); - for (const auto &[_, connections] : m_connMap) { - for (auto *conn : connections) { - delete conn; - } - } -} } // namespace Acts diff --git a/Examples/Detectors/GenericDetector/include/ActsExamples/GenericDetector/ProtoLayerCreatorT.hpp b/Examples/Detectors/GenericDetector/include/ActsExamples/GenericDetector/ProtoLayerCreatorT.hpp index fc4fa4c1459..977c11d9121 100644 --- a/Examples/Detectors/GenericDetector/include/ActsExamples/GenericDetector/ProtoLayerCreatorT.hpp +++ b/Examples/Detectors/GenericDetector/include/ActsExamples/GenericDetector/ProtoLayerCreatorT.hpp @@ -218,8 +218,8 @@ ProtoLayerCreatorT::centralProtoLayers( double moduleHalfY = m_cfg.centralModuleHalfY.at(icl); double moduleThickness = m_cfg.centralModuleThickness.at(icl); // create the shared module - std::shared_ptr moduleBounds( - new Acts::RectangleBounds(moduleHalfX, moduleHalfY)); + auto moduleBounds = + std::make_shared(moduleHalfX, moduleHalfY); std::size_t nCentralModules = m_cfg.centralModuleBinningSchema.at(icl).first * m_cfg.centralModuleBinningSchema.at(icl).second; @@ -414,15 +414,14 @@ ProtoLayerCreatorT::createProtoLayers( double moduleHalfY = m_cfg.posnegModuleHalfY.at(ipnl).at(ipnR); // (1) module bounds // create the bounds - Acts::PlanarBounds* pBounds = nullptr; + std::shared_ptr moduleBounds; if (moduleMaxHalfX != 0. && moduleMinHalfX != moduleMaxHalfX) { - pBounds = new Acts::TrapezoidBounds(moduleMinHalfX, moduleMaxHalfX, - moduleHalfY); + moduleBounds = std::make_shared( + moduleMinHalfX, moduleMaxHalfX, moduleHalfY); } else { - pBounds = new Acts::RectangleBounds(moduleMinHalfX, moduleHalfY); + moduleBounds = std::make_shared(moduleMinHalfX, + moduleHalfY); } - // now create the shared bounds from it - std::shared_ptr moduleBounds(pBounds); // (2)) module material // create the Module material from input std::shared_ptr moduleMaterialPtr = diff --git a/Examples/Detectors/MagneticField/src/FieldMapRootIo.cpp b/Examples/Detectors/MagneticField/src/FieldMapRootIo.cpp index bcc93238364..48e2e634d65 100644 --- a/Examples/Detectors/MagneticField/src/FieldMapRootIo.cpp +++ b/Examples/Detectors/MagneticField/src/FieldMapRootIo.cpp @@ -32,7 +32,7 @@ ActsExamples::makeMagneticFieldMapRzFromRoot( // components of magnetic field on grid points std::vector bField; // [1] Read in file and fill values - TFile* inputFile = TFile::Open(fieldMapFile.c_str()); + std::unique_ptr inputFile(TFile::Open(fieldMapFile.c_str())); if (inputFile == nullptr) { throw std::runtime_error("file does not exist"); } @@ -62,7 +62,6 @@ ActsExamples::makeMagneticFieldMapRzFromRoot( zPos.push_back(z); bField.push_back(Acts::Vector2(Br, Bz)); } - delete inputFile; /// [2] use helper function in core return Acts::fieldMapRZ(localToGlobalBin, rPos, zPos, bField, lengthUnit, BFieldUnit, firstQuadrant); @@ -84,7 +83,7 @@ ActsExamples::makeMagneticFieldMapXyzFromRoot( // components of magnetic field on grid points std::vector bField; // [1] Read in file and fill values - TFile* inputFile = TFile::Open(fieldMapFile.c_str()); + std::unique_ptr inputFile(TFile::Open(fieldMapFile.c_str())); if (inputFile == nullptr) { throw std::runtime_error("file does not exist"); } @@ -118,7 +117,6 @@ ActsExamples::makeMagneticFieldMapXyzFromRoot( zPos.push_back(z); bField.push_back(Acts::Vector3(Bx, By, Bz)); } - delete inputFile; return Acts::fieldMapXYZ(localToGlobalBin, xPos, yPos, zPos, bField, lengthUnit, BFieldUnit, firstOctant); diff --git a/Examples/Io/Root/include/ActsExamples/Io/Root/RootAthenaNTupleReader.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/RootAthenaNTupleReader.hpp index 7f4d6f7bc73..e6bba0782eb 100644 --- a/Examples/Io/Root/include/ActsExamples/Io/Root/RootAthenaNTupleReader.hpp +++ b/Examples/Io/Root/include/ActsExamples/Io/Root/RootAthenaNTupleReader.hpp @@ -178,6 +178,8 @@ class RootAthenaNTupleReader : public ActsExamples::IReader { /// @param config The Configuration struct RootAthenaNTupleReader(const Config &config, Acts::Logging::Level level); + ~RootAthenaNTupleReader() override; + /// Framework name() method std::string name() const final { return "RootAthenaNTupleReader"; } @@ -214,7 +216,7 @@ class RootAthenaNTupleReader : public ActsExamples::IReader { std::size_t m_events = 0; /// The input tree name - TChain *m_inputChain = nullptr; + std::unique_ptr m_inputChain; /// The handle to branches in current event BranchPointerWrapper m_branches; diff --git a/Examples/Io/Root/include/ActsExamples/Io/Root/RootMaterialTrackReader.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/RootMaterialTrackReader.hpp index 3c3bf2aece3..4c95c7e8d1d 100644 --- a/Examples/Io/Root/include/ActsExamples/Io/Root/RootMaterialTrackReader.hpp +++ b/Examples/Io/Root/include/ActsExamples/Io/Root/RootMaterialTrackReader.hpp @@ -94,7 +94,7 @@ class RootMaterialTrackReader : public IReader { std::size_t m_batchSize = 0; /// The input tree name - TChain* m_inputChain = nullptr; + std::unique_ptr m_inputChain; /// Event identifier. std::uint32_t m_eventId = 0; diff --git a/Examples/Io/Root/include/ActsExamples/Io/Root/RootParticleReader.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/RootParticleReader.hpp index 0bcd108570c..1e1e4f2adde 100644 --- a/Examples/Io/Root/include/ActsExamples/Io/Root/RootParticleReader.hpp +++ b/Examples/Io/Root/include/ActsExamples/Io/Root/RootParticleReader.hpp @@ -83,7 +83,7 @@ class RootParticleReader : public IReader { std::size_t m_events = 0; /// The input tree name - TChain* m_inputChain = nullptr; + std::unique_ptr m_inputChain; /// Event identifier. std::uint32_t m_eventId = 0; diff --git a/Examples/Io/Root/include/ActsExamples/Io/Root/RootSimHitReader.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/RootSimHitReader.hpp index bf05678cd8f..7b784b87a58 100644 --- a/Examples/Io/Root/include/ActsExamples/Io/Root/RootSimHitReader.hpp +++ b/Examples/Io/Root/include/ActsExamples/Io/Root/RootSimHitReader.hpp @@ -48,6 +48,8 @@ class RootSimHitReader : public IReader { /// @param config The Configuration struct RootSimHitReader(const Config &config, Acts::Logging::Level level); + ~RootSimHitReader() override; + /// Framework name() method std::string name() const override { return "RootSimHitReader"; } @@ -79,7 +81,7 @@ class RootSimHitReader : public IReader { std::vector> m_eventMap; /// The input tree name - TChain *m_inputChain = nullptr; + std::unique_ptr m_inputChain; /// The keys we have in the ROOT file constexpr static std::array m_floatKeys = { diff --git a/Examples/Io/Root/include/ActsExamples/Io/Root/RootTrackSummaryReader.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/RootTrackSummaryReader.hpp index 71ff807fb32..1f43918c82b 100644 --- a/Examples/Io/Root/include/ActsExamples/Io/Root/RootTrackSummaryReader.hpp +++ b/Examples/Io/Root/include/ActsExamples/Io/Root/RootTrackSummaryReader.hpp @@ -92,7 +92,7 @@ class RootTrackSummaryReader : public IReader { std::size_t m_events = 0; /// The input tree name - TChain* m_inputChain = nullptr; + std::unique_ptr m_inputChain; /// the event number std::uint32_t m_eventNr{0}; diff --git a/Examples/Io/Root/include/ActsExamples/Io/Root/RootVertexReader.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/RootVertexReader.hpp index 46afe962bdb..b40c0b9ba6b 100644 --- a/Examples/Io/Root/include/ActsExamples/Io/Root/RootVertexReader.hpp +++ b/Examples/Io/Root/include/ActsExamples/Io/Root/RootVertexReader.hpp @@ -82,7 +82,7 @@ class RootVertexReader : public IReader { std::size_t m_events = 0; /// The input tree name - TChain* m_inputChain = nullptr; + std::unique_ptr m_inputChain; /// Event identifier. std::uint32_t m_eventId = 0; diff --git a/Examples/Io/Root/src/RootAthenaNTupleReader.cpp b/Examples/Io/Root/src/RootAthenaNTupleReader.cpp index ac06349c595..bf61b919c5b 100644 --- a/Examples/Io/Root/src/RootAthenaNTupleReader.cpp +++ b/Examples/Io/Root/src/RootAthenaNTupleReader.cpp @@ -43,7 +43,7 @@ ActsExamples::RootAthenaNTupleReader::RootAthenaNTupleReader( m_outputRecoVtxParameters.initialize(m_cfg.outputRecoVtxParameters); m_outputBeamspotConstraint.initialize(m_cfg.outputBeamspotConstraint); - m_inputChain = new TChain(m_cfg.inputTreeName.c_str()); + m_inputChain = std::make_unique(m_cfg.inputTreeName.c_str()); // unused event identifier std::int32_t eventNumber = 0; @@ -116,6 +116,8 @@ ActsExamples::RootAthenaNTupleReader::RootAthenaNTupleReader( ACTS_DEBUG("The full chain has " << m_events << " entries."); } +ActsExamples::RootAthenaNTupleReader::~RootAthenaNTupleReader() = default; + ActsExamples::ProcessCode ActsExamples::RootAthenaNTupleReader::read( const ActsExamples::AlgorithmContext& context) { ACTS_DEBUG("Trying to read track parameters from ntuple."); diff --git a/Examples/Io/Root/src/RootBFieldWriter.cpp b/Examples/Io/Root/src/RootBFieldWriter.cpp index b8cb8b6c104..894636d61c9 100644 --- a/Examples/Io/Root/src/RootBFieldWriter.cpp +++ b/Examples/Io/Root/src/RootBFieldWriter.cpp @@ -48,13 +48,13 @@ void RootBFieldWriter::run(const Config& config, // Setup ROOT I/O ACTS_INFO("Registering new ROOT output File : " << config.fileName); - TFile* outputFile = - TFile::Open(config.fileName.c_str(), config.fileMode.c_str()); + std::unique_ptr outputFile( + TFile::Open(config.fileName.c_str(), config.fileMode.c_str())); if (outputFile == nullptr) { throw std::ios_base::failure("Could not open '" + config.fileName + "'"); } TTree* outputTree = new TTree(config.treeName.c_str(), - config.treeName.c_str(), 99, outputFile); + config.treeName.c_str(), 99, outputFile.get()); if (outputTree == nullptr) { throw std::bad_alloc(); } @@ -277,6 +277,5 @@ void RootBFieldWriter::run(const Config& config, // Tear down ROOT I/O ACTS_INFO("Closing and Writing ROOT output File : " << config.fileName); outputTree->Write(); - delete outputFile; } } // namespace ActsExamples diff --git a/Examples/Io/Root/src/RootMaterialTrackReader.cpp b/Examples/Io/Root/src/RootMaterialTrackReader.cpp index 70b2ab8d997..b7e5e0ef4f2 100644 --- a/Examples/Io/Root/src/RootMaterialTrackReader.cpp +++ b/Examples/Io/Root/src/RootMaterialTrackReader.cpp @@ -34,7 +34,7 @@ RootMaterialTrackReader::RootMaterialTrackReader(const Config& config, throw std::invalid_argument{"No input files given"}; } - m_inputChain = new TChain(m_cfg.treeName.c_str()); + m_inputChain = std::make_unique(m_cfg.treeName.c_str()); // loop over the input files for (const auto& inputFile : m_cfg.fileList) { @@ -103,8 +103,6 @@ RootMaterialTrackReader::RootMaterialTrackReader(const Config& config, } RootMaterialTrackReader::~RootMaterialTrackReader() { - delete m_inputChain; - delete m_step_x; delete m_step_y; delete m_step_z; diff --git a/Examples/Io/Root/src/RootParticleReader.cpp b/Examples/Io/Root/src/RootParticleReader.cpp index 631fc25ef3e..0eafeaa666b 100644 --- a/Examples/Io/Root/src/RootParticleReader.cpp +++ b/Examples/Io/Root/src/RootParticleReader.cpp @@ -28,7 +28,7 @@ RootParticleReader::RootParticleReader(const RootParticleReader::Config& config, : IReader(), m_cfg(config), m_logger(Acts::getDefaultLogger(name(), level)) { - m_inputChain = new TChain(m_cfg.treeName.c_str()); + m_inputChain = std::make_unique(m_cfg.treeName.c_str()); if (m_cfg.filePath.empty()) { throw std::invalid_argument("Missing input filename"); diff --git a/Examples/Io/Root/src/RootSimHitReader.cpp b/Examples/Io/Root/src/RootSimHitReader.cpp index 4f0d805dc7e..407c70c5dea 100644 --- a/Examples/Io/Root/src/RootSimHitReader.cpp +++ b/Examples/Io/Root/src/RootSimHitReader.cpp @@ -29,7 +29,7 @@ RootSimHitReader::RootSimHitReader(const RootSimHitReader::Config& config, : IReader(), m_cfg(config), m_logger(Acts::getDefaultLogger(name(), level)) { - m_inputChain = new TChain(m_cfg.treeName.c_str()); + m_inputChain = std::make_unique(m_cfg.treeName.c_str()); if (m_cfg.filePath.empty()) { throw std::invalid_argument("Missing input filename"); @@ -103,6 +103,8 @@ RootSimHitReader::RootSimHitReader(const RootSimHitReader::Config& config, << availableEvents().second); } +RootSimHitReader::~RootSimHitReader() = default; + std::pair RootSimHitReader::availableEvents() const { return {std::get<0>(m_eventMap.front()), std::get<0>(m_eventMap.back()) + 1}; } diff --git a/Examples/Io/Root/src/RootTrackSummaryReader.cpp b/Examples/Io/Root/src/RootTrackSummaryReader.cpp index 9ff3590271a..33da0026ef7 100644 --- a/Examples/Io/Root/src/RootTrackSummaryReader.cpp +++ b/Examples/Io/Root/src/RootTrackSummaryReader.cpp @@ -31,7 +31,7 @@ RootTrackSummaryReader::RootTrackSummaryReader( : IReader(), m_logger{Acts::getDefaultLogger(name(), level)}, m_cfg(config) { - m_inputChain = new TChain(m_cfg.treeName.c_str()); + m_inputChain = std::make_unique(m_cfg.treeName.c_str()); if (m_cfg.filePath.empty()) { throw std::invalid_argument("Missing input filename"); diff --git a/Examples/Io/Root/src/RootVertexReader.cpp b/Examples/Io/Root/src/RootVertexReader.cpp index 31a8e6d5bec..d2d2848749d 100644 --- a/Examples/Io/Root/src/RootVertexReader.cpp +++ b/Examples/Io/Root/src/RootVertexReader.cpp @@ -28,7 +28,7 @@ RootVertexReader::RootVertexReader(const RootVertexReader::Config& config, : IReader(), m_cfg(config), m_logger(Acts::getDefaultLogger(name(), level)) { - m_inputChain = new TChain(m_cfg.treeName.c_str()); + m_inputChain = std::make_unique(m_cfg.treeName.c_str()); if (m_cfg.filePath.empty()) { throw std::invalid_argument("Missing input filename"); diff --git a/Examples/Io/Root/src/detail/NuclearInteractionParametrisation.cpp b/Examples/Io/Root/src/detail/NuclearInteractionParametrisation.cpp index 174f3648ce1..eb1bbe838e8 100644 --- a/Examples/Io/Root/src/detail/NuclearInteractionParametrisation.cpp +++ b/Examples/Io/Root/src/detail/NuclearInteractionParametrisation.cpp @@ -32,15 +32,20 @@ namespace { /// @return The location in a standard normal distribution float gaussianValue(TH1F const* histo, const float mom) { // Get the cumulative probability distribution - TH1F* normalised = static_cast(histo->DrawNormalized()); - TH1F* cumulative = static_cast(normalised->GetCumulative()); + + // DrawNormalized and GetCumulative return pointers to histograms where ROOT + // transfers ownership to the caller. + std::unique_ptr normalised( + dynamic_cast(histo->DrawNormalized())); + std::unique_ptr cumulative( + dynamic_cast(normalised->GetCumulative())); + assert(cumulative); + assert(normalised); // Find the cumulative probability const float binContent = cumulative->GetBinContent(cumulative->FindBin(mom)); // Transform the probability to an entry in a standard normal distribution const float value = TMath::ErfInverse(2. * binContent - 1.); - delete (normalised); - delete (cumulative); return value; } From edad4c94bd83e100419d4a6d2f40f603fceaab7e Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 22 Nov 2024 13:50:15 +0100 Subject: [PATCH 6/8] feat(util): Add `overloaded` helper (#3816) This is useful in combination with `std::visit`. With this, you can do something like ```cpp struct A {}; std::variant var; var = 42; std::visit(overloaded{ [](int) { BOOST_CHECK(true); }, [](double) { BOOST_CHECK(false); }, [](A) { BOOST_CHECK(false); }, }, var); ``` which can be convenient. I'm using this in https://github.com/acts-project/acts/pull/3869 --- Core/include/Acts/Utilities/Helpers.hpp | 17 +++++++++++++++++ Tests/UnitTests/Core/Utilities/HelpersTests.cpp | 15 +++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/Core/include/Acts/Utilities/Helpers.hpp b/Core/include/Acts/Utilities/Helpers.hpp index 4bf9d1c89c3..c59555fd848 100644 --- a/Core/include/Acts/Utilities/Helpers.hpp +++ b/Core/include/Acts/Utilities/Helpers.hpp @@ -204,4 +204,21 @@ bool rangeContainsValue(const R& range, const T& value) { return std::ranges::find(range, value) != std::ranges::end(range); } +/// Helper struct that can turn a set of lambdas into a single entity with +/// overloaded call operator. This can be useful for example in a std::visit +/// call. +/// ```cpp +/// std::visit(overloaded{ +/// [](const int& i) { std::cout << "int: " << i << std::endl; }, +/// [](const std::string& s) { std::cout << "string: " << s << std::endl; }, +/// }, variant); +/// ``` +template +struct overloaded : Ts... { + using Ts::operator()...; +}; + +template +overloaded(Ts...) -> overloaded; + } // namespace Acts diff --git a/Tests/UnitTests/Core/Utilities/HelpersTests.cpp b/Tests/UnitTests/Core/Utilities/HelpersTests.cpp index 85e8454d052..67064306967 100644 --- a/Tests/UnitTests/Core/Utilities/HelpersTests.cpp +++ b/Tests/UnitTests/Core/Utilities/HelpersTests.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include using namespace Acts::VectorHelpers; @@ -310,6 +311,20 @@ BOOST_AUTO_TEST_CASE(incidentAnglesTest) { } } +BOOST_AUTO_TEST_CASE(Overloaded) { + struct A {}; + std::variant var; + + var = 42; + + std::visit(overloaded{ + [](int) { BOOST_CHECK(true); }, + [](double) { BOOST_CHECK(false); }, + [](A) { BOOST_CHECK(false); }, + }, + var); +} + BOOST_AUTO_TEST_SUITE_END() } // namespace Acts::Test From 306ae23993fea1e8fb848228ecee874ca50f3faa Mon Sep 17 00:00:00 2001 From: Pierfrancesco Butti Date: Fri, 22 Nov 2024 19:05:08 +0100 Subject: [PATCH 7/8] fix: Add check on expected measurements on surface before marking as hole (#3892) Check expected measurement during track finding before marking state as hole @andiwand --- Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp b/Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp index 35acbc49feb..315dd2379b0 100644 --- a/Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp +++ b/Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp @@ -739,7 +739,7 @@ class CombinatorialKalmanFilter { slRange = m_sourceLinkAccessor(*surface); hasMeasurements = slRange->first != slRange->second; } - bool isHole = isSensitive && !hasMeasurements; + bool isHole = isSensitive && expectMeasurements && !hasMeasurements; if (isHole) { ACTS_VERBOSE("Detected hole before measurement selection on surface " From b30f8dfe86e2ed940fac02bbe54efdfe2cddaac0 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Sat, 23 Nov 2024 10:18:35 +0100 Subject: [PATCH 8/8] feat: Add statistics to propagation (#3450) This is an attempt to centralize statistics about the propagation which includes stepping and navigation. The intention is to monitor these quantities in the CI and to use them as comparison for different stepper / navigator implementations. --- .../Acts/Navigation/DetectorNavigator.hpp | 4 +++ Core/include/Acts/Propagator/AtlasStepper.hpp | 4 +++ .../Acts/Propagator/DirectNavigator.hpp | 4 +++ Core/include/Acts/Propagator/EigenStepper.hpp | 5 ++- Core/include/Acts/Propagator/EigenStepper.ipp | 15 +++++++- .../Acts/Propagator/MultiEigenStepperLoop.hpp | 4 +++ Core/include/Acts/Propagator/Navigator.hpp | 11 +++--- .../Acts/Propagator/NavigatorStatistics.hpp | 26 ++++++++++++++ Core/include/Acts/Propagator/Propagator.ipp | 3 ++ .../Acts/Propagator/PropagatorResult.hpp | 4 +++ .../Acts/Propagator/PropagatorState.hpp | 4 +++ .../Acts/Propagator/PropagatorStatistics.hpp | 26 ++++++++++++++ .../Acts/Propagator/StepperStatistics.hpp | 34 ++++++++++++++++++ .../Acts/Propagator/StraightLineStepper.hpp | 14 +++++++- Core/include/Acts/Propagator/SympyStepper.hpp | 12 ++----- .../Acts/Propagator/TryAllNavigator.hpp | 4 +++ .../include/Acts/Propagator/VoidNavigator.hpp | 4 +++ Core/src/Propagator/SympyStepper.cpp | 12 ++++++- .../Propagation/PropagatorInterface.hpp | 2 ++ .../EventData/PropagationSummary.hpp | 4 +++ .../Io/Root/RootPropagationSummaryWriter.hpp | 19 +++++----- .../Root/src/RootPropagationStepsWriter.cpp | 7 ++-- .../Root/src/RootPropagationSummaryWriter.cpp | 36 +++++++++++-------- Examples/Python/tests/root_file_hashes.txt | 2 +- .../Core/Propagator/SympyStepperTests.cpp | 23 ------------ 25 files changed, 214 insertions(+), 69 deletions(-) create mode 100644 Core/include/Acts/Propagator/NavigatorStatistics.hpp create mode 100644 Core/include/Acts/Propagator/PropagatorStatistics.hpp create mode 100644 Core/include/Acts/Propagator/StepperStatistics.hpp diff --git a/Core/include/Acts/Navigation/DetectorNavigator.hpp b/Core/include/Acts/Navigation/DetectorNavigator.hpp index 61d8525106c..0ffcf1446bc 100644 --- a/Core/include/Acts/Navigation/DetectorNavigator.hpp +++ b/Core/include/Acts/Navigation/DetectorNavigator.hpp @@ -17,6 +17,7 @@ #include "Acts/Geometry/Layer.hpp" #include "Acts/Navigation/NavigationState.hpp" #include "Acts/Propagator/NavigatorOptions.hpp" +#include "Acts/Propagator/NavigatorStatistics.hpp" #include "Acts/Propagator/Propagator.hpp" #include "Acts/Surfaces/BoundaryTolerance.hpp" #include "Acts/Surfaces/Surface.hpp" @@ -68,6 +69,9 @@ class DetectorNavigator { bool targetReached = false; /// Navigation state : a break has been detected bool navigationBreak = false; + + /// Navigation statistics + NavigatorStatistics statistics; }; /// Constructor with configuration object diff --git a/Core/include/Acts/Propagator/AtlasStepper.hpp b/Core/include/Acts/Propagator/AtlasStepper.hpp index f31aadbffab..88cfd39e548 100644 --- a/Core/include/Acts/Propagator/AtlasStepper.hpp +++ b/Core/include/Acts/Propagator/AtlasStepper.hpp @@ -21,6 +21,7 @@ #include "Acts/MagneticField/MagneticFieldProvider.hpp" #include "Acts/Propagator/ConstrainedStep.hpp" #include "Acts/Propagator/StepperOptions.hpp" +#include "Acts/Propagator/StepperStatistics.hpp" #include "Acts/Propagator/detail/SteppingHelper.hpp" #include "Acts/Surfaces/Surface.hpp" #include "Acts/Utilities/Intersection.hpp" @@ -305,6 +306,9 @@ class AtlasStepper { /// buffer & formatting for consistent output std::size_t debugPfxWidth = 30; std::size_t debugMsgWidth = 50; + + /// The statistics of the stepper + StepperStatistics statistics; }; explicit AtlasStepper(std::shared_ptr bField) diff --git a/Core/include/Acts/Propagator/DirectNavigator.hpp b/Core/include/Acts/Propagator/DirectNavigator.hpp index eb9db91e71f..3356ab395c4 100644 --- a/Core/include/Acts/Propagator/DirectNavigator.hpp +++ b/Core/include/Acts/Propagator/DirectNavigator.hpp @@ -14,6 +14,7 @@ #include "Acts/Geometry/TrackingGeometry.hpp" #include "Acts/Geometry/TrackingVolume.hpp" #include "Acts/Propagator/NavigatorOptions.hpp" +#include "Acts/Propagator/NavigatorStatistics.hpp" #include "Acts/Propagator/Propagator.hpp" #include "Acts/Surfaces/BoundaryTolerance.hpp" #include "Acts/Surfaces/Surface.hpp" @@ -75,6 +76,9 @@ class DirectNavigator { /// Navigation state - external interface: a break has been detected bool navigationBreak = false; + /// Navigation statistics + NavigatorStatistics statistics; + const Surface* navSurface() const { return options.surfaces.at(surfaceIndex); } diff --git a/Core/include/Acts/Propagator/EigenStepper.hpp b/Core/include/Acts/Propagator/EigenStepper.hpp index fb1062b0c9b..09df3ce3167 100644 --- a/Core/include/Acts/Propagator/EigenStepper.hpp +++ b/Core/include/Acts/Propagator/EigenStepper.hpp @@ -13,7 +13,6 @@ #include "Acts/Definitions/Algebra.hpp" #include "Acts/Definitions/Tolerance.hpp" -#include "Acts/Definitions/Units.hpp" #include "Acts/EventData/TrackParameters.hpp" #include "Acts/EventData/detail/CorrectedTransformationFreeToBound.hpp" #include "Acts/Geometry/GeometryContext.hpp" @@ -23,6 +22,7 @@ #include "Acts/Propagator/EigenStepperDefaultExtension.hpp" #include "Acts/Propagator/PropagatorTraits.hpp" #include "Acts/Propagator/StepperOptions.hpp" +#include "Acts/Propagator/StepperStatistics.hpp" #include "Acts/Propagator/detail/SteppingHelper.hpp" #include "Acts/Utilities/Intersection.hpp" #include "Acts/Utilities/Result.hpp" @@ -164,6 +164,9 @@ class EigenStepper { /// k_i elements of the momenta std::array kQoP{}; } stepData; + + /// Statistics of the stepper + StepperStatistics statistics; }; /// Constructor requires knowledge of the detector's magnetic field diff --git a/Core/include/Acts/Propagator/EigenStepper.ipp b/Core/include/Acts/Propagator/EigenStepper.ipp index 84b305ae431..4ee3a41b04a 100644 --- a/Core/include/Acts/Propagator/EigenStepper.ipp +++ b/Core/include/Acts/Propagator/EigenStepper.ipp @@ -6,6 +6,7 @@ // 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 "Acts/Definitions/Direction.hpp" #include "Acts/EventData/TransformationHelpers.hpp" #include "Acts/Propagator/ConstrainedStep.hpp" #include "Acts/Propagator/EigenStepperError.hpp" @@ -259,7 +260,9 @@ Acts::Result Acts::EigenStepper::step( // Select and adjust the appropriate Runge-Kutta step size as given // ATL-SOFT-PUB-2009-001 while (true) { - nStepTrials++; + ++nStepTrials; + ++state.stepping.statistics.nAttemptedSteps; + auto res = tryRungeKuttaStep(h); if (!res.ok()) { return res.error(); @@ -268,6 +271,8 @@ Acts::Result Acts::EigenStepper::step( break; } + ++state.stepping.statistics.nRejectedSteps; + const double stepSizeScaling = calcStepSizeScaling(errorEstimate); h *= stepSizeScaling; @@ -351,6 +356,14 @@ Acts::Result Acts::EigenStepper::step( ++state.stepping.nSteps; state.stepping.nStepTrials += nStepTrials; + ++state.stepping.statistics.nSuccessfulSteps; + if (state.options.direction != + Direction::fromScalarZeroAsPositive(initialH)) { + ++state.stepping.statistics.nReverseSteps; + } + state.stepping.statistics.pathLength += h; + state.stepping.statistics.absolutePathLength += std::abs(h); + const double stepSizeScaling = calcStepSizeScaling(errorEstimate); const double nextAccuracy = std::abs(h * stepSizeScaling); const double previousAccuracy = std::abs(state.stepping.stepSize.accuracy()); diff --git a/Core/include/Acts/Propagator/MultiEigenStepperLoop.hpp b/Core/include/Acts/Propagator/MultiEigenStepperLoop.hpp index 1bb4ab8f55a..e21bdb2365e 100644 --- a/Core/include/Acts/Propagator/MultiEigenStepperLoop.hpp +++ b/Core/include/Acts/Propagator/MultiEigenStepperLoop.hpp @@ -25,6 +25,7 @@ #include "Acts/Propagator/MultiStepperError.hpp" #include "Acts/Propagator/Propagator.hpp" #include "Acts/Propagator/StepperOptions.hpp" +#include "Acts/Propagator/StepperStatistics.hpp" #include "Acts/Propagator/detail/LoopStepperUtils.hpp" #include "Acts/Surfaces/Surface.hpp" #include "Acts/Utilities/Intersection.hpp" @@ -219,6 +220,9 @@ class MultiEigenStepperLoop : public EigenStepper { /// reached a surface std::optional stepCounterAfterFirstComponentOnSurface; + /// The stepper statistics + StepperStatistics statistics; + /// No default constructor is provided State() = delete; diff --git a/Core/include/Acts/Propagator/Navigator.hpp b/Core/include/Acts/Propagator/Navigator.hpp index c2a9427257c..a02e0958160 100644 --- a/Core/include/Acts/Propagator/Navigator.hpp +++ b/Core/include/Acts/Propagator/Navigator.hpp @@ -8,13 +8,13 @@ #pragma once -#include "Acts/Definitions/Units.hpp" #include "Acts/Geometry/GeometryIdentifier.hpp" #include "Acts/Geometry/Layer.hpp" #include "Acts/Geometry/TrackingGeometry.hpp" #include "Acts/Geometry/TrackingVolume.hpp" #include "Acts/Propagator/ConstrainedStep.hpp" #include "Acts/Propagator/NavigatorOptions.hpp" +#include "Acts/Propagator/NavigatorStatistics.hpp" #include "Acts/Surfaces/BoundaryTolerance.hpp" #include "Acts/Surfaces/Surface.hpp" #include "Acts/Utilities/Logger.hpp" @@ -176,9 +176,12 @@ class Navigator { bool targetReached = false; /// Navigation state : a break has been detected bool navigationBreak = false; - // The navigation stage (@todo: integrate break, target) + /// The navigation stage (@todo: integrate break, target) Stage navigationStage = Stage::undefined; + /// Navigation statistics + NavigatorStatistics statistics; + void reset() { navSurfaces.clear(); navSurfaceIndex = navSurfaces.size(); @@ -427,6 +430,7 @@ class Navigator { << "No targets found, we got lost! Attempt renavigation."); state.navigation.reset(); + ++state.navigation.statistics.nRenavigations; // We might have punched through a boundary and entered another volume // so we have to reinitialize @@ -576,6 +580,7 @@ class Navigator { state.navigation.navBoundaries.clear(); state.navigation.navBoundaryIndex = state.navigation.navBoundaries.size(); + ++state.navigation.statistics.nVolumeSwitches; } } else { // Set the navigation stage back to boundary target @@ -772,8 +777,6 @@ class Navigator { /// @return boolean return triggers exit to stepper template bool targetLayers(propagator_state_t& state, const stepper_t& stepper) const { - using namespace UnitLiterals; - if (state.navigation.navigationBreak) { return false; } diff --git a/Core/include/Acts/Propagator/NavigatorStatistics.hpp b/Core/include/Acts/Propagator/NavigatorStatistics.hpp new file mode 100644 index 00000000000..fd73d36c568 --- /dev/null +++ b/Core/include/Acts/Propagator/NavigatorStatistics.hpp @@ -0,0 +1,26 @@ +// 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/. + +#pragma once + +#include + +namespace Acts { + +/// @struct NavigatorStatistics +/// +/// @brief A struct to hold statistics of the navigator +struct NavigatorStatistics { + /// Number of renavigation attempts + std::size_t nRenavigations = 0; + + /// Number of volume switches + std::size_t nVolumeSwitches = 0; +}; + +} // namespace Acts diff --git a/Core/include/Acts/Propagator/Propagator.ipp b/Core/include/Acts/Propagator/Propagator.ipp index a7c12309bb7..8a7c560a725 100644 --- a/Core/include/Acts/Propagator/Propagator.ipp +++ b/Core/include/Acts/Propagator/Propagator.ipp @@ -341,6 +341,9 @@ void Acts::Propagator::moveStateToResult(propagator_state_t& state, result.steps = state.steps; result.pathLength = state.pathLength; + + result.statistics.stepping = state.stepping.statistics; + result.statistics.navigation = state.navigation.statistics; } template diff --git a/Core/include/Acts/Propagator/PropagatorResult.hpp b/Core/include/Acts/Propagator/PropagatorResult.hpp index 232211b8495..a67543f7b4b 100644 --- a/Core/include/Acts/Propagator/PropagatorResult.hpp +++ b/Core/include/Acts/Propagator/PropagatorResult.hpp @@ -9,6 +9,7 @@ #pragma once #include "Acts/Definitions/TrackParametrization.hpp" +#include "Acts/Propagator/PropagatorStatistics.hpp" #include "Acts/Utilities/detail/Extendable.hpp" #include @@ -36,6 +37,9 @@ struct PropagatorResult : private detail::Extendable { /// Signed distance over which the parameters were propagated double pathLength = 0.; + + /// Propagator statistics + PropagatorStatistics statistics; }; } // namespace Acts diff --git a/Core/include/Acts/Propagator/PropagatorState.hpp b/Core/include/Acts/Propagator/PropagatorState.hpp index 29e1baeeb30..03346cfd57d 100644 --- a/Core/include/Acts/Propagator/PropagatorState.hpp +++ b/Core/include/Acts/Propagator/PropagatorState.hpp @@ -9,6 +9,7 @@ #pragma once #include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Propagator/PropagatorStatistics.hpp" #include "Acts/Utilities/detail/Extendable.hpp" #include @@ -72,6 +73,9 @@ struct PropagatorState : private detail::Extendable { /// Signed distance over which the parameters were propagated double pathLength = 0.; + + /// Statistics of the propagation + PropagatorStatistics statistics; }; } // namespace Acts diff --git a/Core/include/Acts/Propagator/PropagatorStatistics.hpp b/Core/include/Acts/Propagator/PropagatorStatistics.hpp new file mode 100644 index 00000000000..843be215bd9 --- /dev/null +++ b/Core/include/Acts/Propagator/PropagatorStatistics.hpp @@ -0,0 +1,26 @@ +// 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/. + +#pragma once + +#include +#include + +namespace Acts { + +/// @struct PropagatorStatistics +/// +/// @brief A struct to hold statistics of the propagator +struct PropagatorStatistics { + /// Statistics of the stepper + StepperStatistics stepping; + /// Statistics of the navigator + NavigatorStatistics navigation; +}; + +} // namespace Acts diff --git a/Core/include/Acts/Propagator/StepperStatistics.hpp b/Core/include/Acts/Propagator/StepperStatistics.hpp new file mode 100644 index 00000000000..64abf5bde00 --- /dev/null +++ b/Core/include/Acts/Propagator/StepperStatistics.hpp @@ -0,0 +1,34 @@ +// 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/. + +#pragma once + +#include + +namespace Acts { + +/// @struct StepperStatistics +/// +/// @brief A struct to hold statistics of the stepper +struct StepperStatistics { + /// Number of attempted steps + std::size_t nAttemptedSteps = 0; + /// Number of rejected steps + std::size_t nRejectedSteps = 0; + /// Number of successful steps + std::size_t nSuccessfulSteps = 0; + /// Number of steps that were reversed + std::size_t nReverseSteps = 0; + + /// Signed sum of the step lengths + double pathLength = 0; + /// Unsigned sum of the step lengths + double absolutePathLength = 0; +}; + +} // namespace Acts diff --git a/Core/include/Acts/Propagator/StraightLineStepper.hpp b/Core/include/Acts/Propagator/StraightLineStepper.hpp index 8ba0d72fe81..18904797fdd 100644 --- a/Core/include/Acts/Propagator/StraightLineStepper.hpp +++ b/Core/include/Acts/Propagator/StraightLineStepper.hpp @@ -23,6 +23,7 @@ #include "Acts/Propagator/ConstrainedStep.hpp" #include "Acts/Propagator/PropagatorTraits.hpp" #include "Acts/Propagator/StepperOptions.hpp" +#include "Acts/Propagator/StepperStatistics.hpp" #include "Acts/Propagator/detail/SteppingHelper.hpp" #include "Acts/Surfaces/BoundaryTolerance.hpp" #include "Acts/Surfaces/Surface.hpp" @@ -142,6 +143,9 @@ class StraightLineStepper { // Cache the geometry context of this propagation std::reference_wrapper geoContext; + + /// Statistics of the stepper + StepperStatistics statistics; }; StraightLineStepper() = default; @@ -430,6 +434,7 @@ class StraightLineStepper { Vector3 dir = direction(state.stepping); state.stepping.pars.template segment<3>(eFreePos0) += h * dir; state.stepping.pars[eFreeTime] += h * dtds; + // Propagate the jacobian if (state.stepping.covTransport) { // The step transport matrix in global coordinates @@ -450,7 +455,14 @@ class StraightLineStepper { ++state.stepping.nSteps; ++state.stepping.nStepTrials; - // return h + ++state.stepping.statistics.nAttemptedSteps; + ++state.stepping.statistics.nSuccessfulSteps; + if (state.options.direction != Direction::fromScalarZeroAsPositive(h)) { + ++state.stepping.statistics.nReverseSteps; + } + state.stepping.statistics.pathLength += h; + state.stepping.statistics.absolutePathLength += std::abs(h); + return h; } }; diff --git a/Core/include/Acts/Propagator/SympyStepper.hpp b/Core/include/Acts/Propagator/SympyStepper.hpp index 1e771a53ba7..3b1a2125a41 100644 --- a/Core/include/Acts/Propagator/SympyStepper.hpp +++ b/Core/include/Acts/Propagator/SympyStepper.hpp @@ -22,6 +22,7 @@ #include "Acts/Propagator/ConstrainedStep.hpp" #include "Acts/Propagator/PropagatorTraits.hpp" #include "Acts/Propagator/StepperOptions.hpp" +#include "Acts/Propagator/StepperStatistics.hpp" #include "Acts/Propagator/detail/SteppingHelper.hpp" namespace Acts { @@ -132,15 +133,8 @@ class SympyStepper { /// The geometry context std::reference_wrapper geoContext; - /// @brief Storage of magnetic field and the sub steps during a RKN4 step - struct { - /// Magnetic field evaulations - Vector3 B_first, B_middle, B_last; - /// k_i of the RKN4 algorithm - Vector3 k1, k2, k3, k4; - /// k_i elements of the momenta - std::array kQoP{}; - } stepData; + /// Statistics of the stepper + StepperStatistics statistics; }; /// Constructor requires knowledge of the detector's magnetic field diff --git a/Core/include/Acts/Propagator/TryAllNavigator.hpp b/Core/include/Acts/Propagator/TryAllNavigator.hpp index 83d7cbc64a4..09f6fb25e25 100644 --- a/Core/include/Acts/Propagator/TryAllNavigator.hpp +++ b/Core/include/Acts/Propagator/TryAllNavigator.hpp @@ -14,6 +14,7 @@ #include "Acts/Geometry/TrackingVolume.hpp" #include "Acts/Propagator/ConstrainedStep.hpp" #include "Acts/Propagator/NavigatorOptions.hpp" +#include "Acts/Propagator/NavigatorStatistics.hpp" #include "Acts/Propagator/detail/NavigationHelpers.hpp" #include "Acts/Surfaces/BoundaryTolerance.hpp" #include "Acts/Surfaces/Surface.hpp" @@ -86,6 +87,9 @@ class TryAllNavigatorBase { bool targetReached = false; /// If a break has been detected bool navigationBreak = false; + + /// Navigation statistics + NavigatorStatistics statistics; }; /// Constructor with configuration object diff --git a/Core/include/Acts/Propagator/VoidNavigator.hpp b/Core/include/Acts/Propagator/VoidNavigator.hpp index d6732998d4b..6b461f79210 100644 --- a/Core/include/Acts/Propagator/VoidNavigator.hpp +++ b/Core/include/Acts/Propagator/VoidNavigator.hpp @@ -9,6 +9,7 @@ #pragma once #include "Acts/Propagator/NavigatorOptions.hpp" +#include "Acts/Propagator/NavigatorStatistics.hpp" namespace Acts { class Surface; @@ -30,6 +31,9 @@ struct VoidNavigator { /// @brief Nested State struct, minimal requirement struct State { Options options; + + /// Navigation statistics + NavigatorStatistics statistics; }; State makeState(const Options& options) const { diff --git a/Core/src/Propagator/SympyStepper.cpp b/Core/src/Propagator/SympyStepper.cpp index a33e1f567bb..d55c073a851 100644 --- a/Core/src/Propagator/SympyStepper.cpp +++ b/Core/src/Propagator/SympyStepper.cpp @@ -144,7 +144,8 @@ Result SympyStepper::stepImpl( double errorEstimate = 0.; while (true) { - nStepTrials++; + ++nStepTrials; + ++state.statistics.nAttemptedSteps; // For details about the factor 4 see ATL-SOFT-PUB-2009-001 Result res = @@ -164,6 +165,8 @@ Result SympyStepper::stepImpl( break; } + ++state.statistics.nRejectedSteps; + const double stepSizeScaling = calcStepSizeScaling(errorEstimate); h *= stepSizeScaling; @@ -186,6 +189,13 @@ Result SympyStepper::stepImpl( ++state.nSteps; state.nStepTrials += nStepTrials; + ++state.statistics.nSuccessfulSteps; + if (stepDirection != Direction::fromScalarZeroAsPositive(initialH)) { + ++state.statistics.nReverseSteps; + } + state.statistics.pathLength += h; + state.statistics.absolutePathLength += std::abs(h); + const double stepSizeScaling = calcStepSizeScaling(errorEstimate); const double nextAccuracy = std::abs(h * stepSizeScaling); const double previousAccuracy = std::abs(state.stepSize.accuracy()); diff --git a/Examples/Algorithms/Propagation/include/ActsExamples/Propagation/PropagatorInterface.hpp b/Examples/Algorithms/Propagation/include/ActsExamples/Propagation/PropagatorInterface.hpp index 2aa3b2292ac..7f113d47b56 100644 --- a/Examples/Algorithms/Propagation/include/ActsExamples/Propagation/PropagatorInterface.hpp +++ b/Examples/Algorithms/Propagation/include/ActsExamples/Propagation/PropagatorInterface.hpp @@ -117,6 +117,8 @@ class ConcretePropagator : public PropagatorInterface { resultValue.template get(); summary.steps = std::move(steppingResults.steps); + summary.statistics = resultValue.statistics; + // Also set the material recording result - if configured if (cfg.recordMaterialInteractions) { auto materialResult = diff --git a/Examples/Framework/include/ActsExamples/EventData/PropagationSummary.hpp b/Examples/Framework/include/ActsExamples/EventData/PropagationSummary.hpp index aa9a736675f..1d1ef44f499 100644 --- a/Examples/Framework/include/ActsExamples/EventData/PropagationSummary.hpp +++ b/Examples/Framework/include/ActsExamples/EventData/PropagationSummary.hpp @@ -10,6 +10,7 @@ #include "Acts/EventData/TrackParameters.hpp" #include "Acts/Propagator/MaterialInteractor.hpp" +#include "Acts/Propagator/PropagatorStatistics.hpp" #include "Acts/Propagator/detail/SteppingLogger.hpp" #include @@ -34,6 +35,9 @@ struct PropagationSummary { /// Steps std::vector steps; + + /// Propagation statistics + Acts::PropagatorStatistics statistics; }; using PropagationSummaries = std::vector; diff --git a/Examples/Io/Root/include/ActsExamples/Io/Root/RootPropagationSummaryWriter.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/RootPropagationSummaryWriter.hpp index c1f6afe9059..f9eea212b12 100644 --- a/Examples/Io/Root/include/ActsExamples/Io/Root/RootPropagationSummaryWriter.hpp +++ b/Examples/Io/Root/include/ActsExamples/Io/Root/RootPropagationSummaryWriter.hpp @@ -8,22 +8,18 @@ #pragma once -#include "Acts/Propagator/detail/SteppingLogger.hpp" #include "Acts/Utilities/Logger.hpp" #include "ActsExamples/Framework/ProcessCode.hpp" #include "ActsExamples/Framework/WriterT.hpp" #include "ActsExamples/Propagation/PropagationAlgorithm.hpp" -#include #include #include -#include class TFile; class TTree; namespace ActsExamples { -struct AlgorithmContext; /// @class RootPropagationSummaryWriter /// @@ -110,10 +106,17 @@ class RootPropagationSummaryWriter : public WriterT { int m_nMaterials = 0; int m_nPortals = 0; - // steper statistics - int m_nSteps = 0; - int m_nStepTrials = 0; - int m_pathLength = 0; + // stepper statistics + std::size_t m_nAttemptedSteps = 0; + std::size_t m_nRejectedSteps = 0; + std::size_t m_nSuccessfulSteps = 0; + std::size_t m_nReverseSteps = 0; + double m_pathLength = 0; + double m_absolutePathLength = 0; + + // navigator statistics + std::size_t m_nRenavigations = 0; + std::size_t m_nVolumeSwitches = 0; }; } // namespace ActsExamples diff --git a/Examples/Io/Root/src/RootPropagationStepsWriter.cpp b/Examples/Io/Root/src/RootPropagationStepsWriter.cpp index c7866e056eb..643956a6ed1 100644 --- a/Examples/Io/Root/src/RootPropagationStepsWriter.cpp +++ b/Examples/Io/Root/src/RootPropagationStepsWriter.cpp @@ -9,15 +9,12 @@ #include "ActsExamples/Io/Root/RootPropagationStepsWriter.hpp" #include "Acts/Definitions/Algebra.hpp" +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Propagator/ConstrainedStep.hpp" #include "Acts/Utilities/Helpers.hpp" #include "Acts/Utilities/VectorHelpers.hpp" #include "ActsExamples/EventData/PropagationSummary.hpp" #include "ActsExamples/Framework/AlgorithmContext.hpp" -#include -#include -#include -#include -#include #include #include diff --git a/Examples/Io/Root/src/RootPropagationSummaryWriter.cpp b/Examples/Io/Root/src/RootPropagationSummaryWriter.cpp index 07a1cfa105f..7df19539c57 100644 --- a/Examples/Io/Root/src/RootPropagationSummaryWriter.cpp +++ b/Examples/Io/Root/src/RootPropagationSummaryWriter.cpp @@ -8,19 +8,11 @@ #include "ActsExamples/Io/Root/RootPropagationSummaryWriter.hpp" -#include "Acts/Definitions/Algebra.hpp" -#include "Acts/Utilities/Helpers.hpp" #include "Acts/Utilities/VectorHelpers.hpp" #include "ActsExamples/Framework/AlgorithmContext.hpp" #include "ActsExamples/Propagation/PropagationAlgorithm.hpp" -#include -#include -#include -#include -#include #include -#include #include #include @@ -77,9 +69,15 @@ RootPropagationSummaryWriter::RootPropagationSummaryWriter( m_outputTree->Branch("nMaterials", &m_nMaterials); m_outputTree->Branch("nPortals", &m_nPortals); - m_outputTree->Branch("nSteps", &m_nSteps); - m_outputTree->Branch("nStepTrials", &m_nStepTrials); + m_outputTree->Branch("nAttemptedSteps", &m_nAttemptedSteps); + m_outputTree->Branch("nRejectedSteps", &m_nRejectedSteps); + m_outputTree->Branch("nSuccessfulSteps", &m_nSuccessfulSteps); + m_outputTree->Branch("nReverseSteps", &m_nReverseSteps); m_outputTree->Branch("pathLength", &m_pathLength); + m_outputTree->Branch("absolutePathLength", &m_absolutePathLength); + + m_outputTree->Branch("nRenavigations", &m_nRenavigations); + m_outputTree->Branch("nVolumeSwitches", &m_nVolumeSwitches); } RootPropagationSummaryWriter::~RootPropagationSummaryWriter() { @@ -133,11 +131,6 @@ ProcessCode RootPropagationSummaryWriter::writeT( m_pt = static_cast(startParameters.transverseMomentum()); m_p = static_cast(startParameters.absoluteMomentum()); - // Stepper statistics - m_nSteps = static_cast(summary.steps.size()); - m_nStepTrials = static_cast(summary.nStepTrials); - m_pathLength = static_cast(summary.pathLength); - m_nMaterials = 0; m_nSensitives = 0; m_nPortals = 0; @@ -160,6 +153,19 @@ ProcessCode RootPropagationSummaryWriter::writeT( } } }); + + // Stepper statistics + m_nAttemptedSteps = summary.statistics.stepping.nAttemptedSteps; + m_nRejectedSteps = summary.statistics.stepping.nRejectedSteps; + m_nSuccessfulSteps = summary.statistics.stepping.nSuccessfulSteps; + m_nReverseSteps = summary.statistics.stepping.nReverseSteps; + m_pathLength = summary.statistics.stepping.pathLength; + m_absolutePathLength = summary.statistics.stepping.absolutePathLength; + + // Navigator statistics + m_nRenavigations = summary.statistics.navigation.nRenavigations; + m_nVolumeSwitches = summary.statistics.navigation.nVolumeSwitches; + m_outputTree->Fill(); } diff --git a/Examples/Python/tests/root_file_hashes.txt b/Examples/Python/tests/root_file_hashes.txt index 4674ce1ce2e..666cb676c39 100644 --- a/Examples/Python/tests/root_file_hashes.txt +++ b/Examples/Python/tests/root_file_hashes.txt @@ -16,7 +16,7 @@ test_itk_seeding__estimatedparams.root: fc042037f12a434f2236df7d225b8ca24209b691 test_itk_seeding__performance_seeding.root: 78ebda54cd0f026ba4b7f316724ffd946de56a932735914baf1b7bba9505c29d test_itk_seeding__particles.root: 907ff693262c0db14b12c74b16586cb20d79caf5f03f93b178943e41ed35a1b6 test_itk_seeding__particles_simulation.root: ef0246069aa697019f28a8b270a68de95312cae5f2f2c74848566c3ce4f70363 -test_propagation__propagation_summary.root: 280c1a6fcfe71974ac39587b4afad27a31640bec42ca6537cc92e2d5e09d7ed6 +test_propagation__propagation_summary.root: 400043dfeed9eda16512ec5fd4a1389f94b98565083f06f439c7b7b59e46c544 test_material_recording__geant4_material_tracks.root: c022b9362249b29f57a07926b20644e3ab4ab8ebcf03f773fbf46c446fc1a0a1 test_truth_tracking_gsf[generic]__trackstates_gsf.root: 4df2c69d5dd7d5446a547651e4e962daf17924f5c8617165a93a3223c8ba18fd test_truth_tracking_gsf[generic]__tracksummary_gsf.root: 8c01d139cb865afa1959c62dbca76f3a1fb8b684c57ea4c2968baa6ffedadb6f diff --git a/Tests/UnitTests/Core/Propagator/SympyStepperTests.cpp b/Tests/UnitTests/Core/Propagator/SympyStepperTests.cpp index fcdf13e9f8a..7ed2255afdc 100644 --- a/Tests/UnitTests/Core/Propagator/SympyStepperTests.cpp +++ b/Tests/UnitTests/Core/Propagator/SympyStepperTests.cpp @@ -12,52 +12,30 @@ #include "Acts/Definitions/Direction.hpp" #include "Acts/Definitions/TrackParametrization.hpp" #include "Acts/Definitions/Units.hpp" -#include "Acts/EventData/Charge.hpp" #include "Acts/EventData/GenericBoundTrackParameters.hpp" #include "Acts/EventData/GenericCurvilinearTrackParameters.hpp" #include "Acts/EventData/ParticleHypothesis.hpp" #include "Acts/EventData/TrackParameters.hpp" #include "Acts/EventData/TransformationHelpers.hpp" -#include "Acts/Geometry/BoundarySurfaceT.hpp" -#include "Acts/Geometry/CuboidVolumeBuilder.hpp" #include "Acts/Geometry/GeometryContext.hpp" -#include "Acts/Geometry/TrackingGeometry.hpp" -#include "Acts/Geometry/TrackingGeometryBuilder.hpp" -#include "Acts/Geometry/TrackingVolume.hpp" #include "Acts/MagneticField/ConstantBField.hpp" #include "Acts/MagneticField/MagneticFieldContext.hpp" #include "Acts/MagneticField/MagneticFieldProvider.hpp" -#include "Acts/MagneticField/NullBField.hpp" -#include "Acts/Material/HomogeneousSurfaceMaterial.hpp" -#include "Acts/Material/HomogeneousVolumeMaterial.hpp" -#include "Acts/Material/MaterialSlab.hpp" -#include "Acts/Propagator/ActorList.hpp" #include "Acts/Propagator/ConstrainedStep.hpp" -#include "Acts/Propagator/MaterialInteractor.hpp" -#include "Acts/Propagator/Navigator.hpp" -#include "Acts/Propagator/Propagator.hpp" #include "Acts/Propagator/SympyStepper.hpp" #include "Acts/Surfaces/BoundaryTolerance.hpp" #include "Acts/Surfaces/CurvilinearSurface.hpp" #include "Acts/Surfaces/PlaneSurface.hpp" -#include "Acts/Surfaces/RectangleBounds.hpp" -#include "Acts/Surfaces/Surface.hpp" #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" -#include "Acts/Tests/CommonHelpers/PredefinedMaterials.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Utilities/Result.hpp" -#include "Acts/Utilities/UnitVectors.hpp" #include -#include #include -#include #include -#include #include #include #include -#include #include #include #include @@ -363,7 +341,6 @@ BOOST_AUTO_TEST_CASE(sympy_stepper_test) { state.fieldCache.template as()); copy.geoContext = state.geoContext; - copy.stepData = state.stepData; return copy; };