diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index f7dfa2bdb97..1c0fc64ff27 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -23,6 +23,8 @@ jobs: - name: "Checkout repository" uses: actions/checkout@v4 + with: + fetch-depth: 0 # To prevent shallow clone - name: 'Download artifact' uses: actions/github-script@v7 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 843980dd82a..084d0c2dbb2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -74,7 +74,7 @@ build_exatrkx_cpu: - git checkout $HEAD_SHA - cd .. - mkdir build - # Here we only do a minimal build without examples to save ressources + # Here we only do a minimal build without examples to save resources - > cmake -B build -S src --preset=gitlab-ci-exatrkx diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf.root b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf.root index e9482480e51..75a481a3e29 100644 Binary files a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf.root and b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf.root differ diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf_ambi.root b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf_ambi.root index 7f919ed5f8b..f9ffefcbdc1 100644 Binary files a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf_ambi.root and b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf_ambi.root differ diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_seeding.root b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_seeding.root index e6496bfcb54..5e072e1393c 100644 Binary files a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_seeding.root and b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_seeding.root differ diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_gauss_notime_hist.root b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_gauss_notime_hist.root index 9f7aad43494..7836b12cd4f 100644 Binary files a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_gauss_notime_hist.root and b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_gauss_notime_hist.root differ diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_grid_time_hist.root b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_grid_time_hist.root index f62e5ec3c89..0980823e57c 100644 Binary files a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_grid_time_hist.root and b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_grid_time_hist.root differ diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/tracksummary_ckf_hist.root b/CI/physmon/reference/trackfinding_ttbar_pu200/tracksummary_ckf_hist.root index 6674c9fbde1..7af2710b5a8 100644 Binary files a/CI/physmon/reference/trackfinding_ttbar_pu200/tracksummary_ckf_hist.root and b/CI/physmon/reference/trackfinding_ttbar_pu200/tracksummary_ckf_hist.root differ diff --git a/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py b/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py index 45c01aedde8..172fa55270a 100755 --- a/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py +++ b/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py @@ -9,6 +9,7 @@ addPythia8, addFatras, addDigitization, + ParticleSelectorConfig, ) from acts.examples.reconstruction import ( addSeeding, @@ -63,6 +64,10 @@ setup.trackingGeometry, setup.field, rnd=rnd, + preSelectParticles=ParticleSelectorConfig( + rho=(0.0, 24 * u.mm), + absZ=(0.0, 1.0 * u.m), + ), ) addDigitization( diff --git a/Core/include/Acts/AmbiguityResolution/GreedyAmbiguityResolution.hpp b/Core/include/Acts/AmbiguityResolution/GreedyAmbiguityResolution.hpp index cffdb128220..078d155a27a 100644 --- a/Core/include/Acts/AmbiguityResolution/GreedyAmbiguityResolution.hpp +++ b/Core/include/Acts/AmbiguityResolution/GreedyAmbiguityResolution.hpp @@ -11,6 +11,7 @@ #include "Acts/EventData/MultiTrajectoryHelpers.hpp" #include "Acts/EventData/SourceLink.hpp" #include "Acts/EventData/TrackContainer.hpp" +#include "Acts/EventData/TrackContainerFrontendConcept.hpp" #include "Acts/Utilities/Delegate.hpp" #include "Acts/Utilities/Logger.hpp" @@ -77,13 +78,11 @@ class GreedyAmbiguityResolution { /// @param state An empty state object which is expected to be default constructed. /// @param sourceLinkHash A functor to acquire a hash from a given source link. /// @param sourceLinkEquality A functor to check equality of two source links. - template class holder_t, typename source_link_hash_t, - typename source_link_equality_t> - void computeInitialState( - const TrackContainer& tracks, - State& state, source_link_hash_t&& sourceLinkHash, - source_link_equality_t&& sourceLinkEquality) const; + template + void computeInitialState(const track_container_t& tracks, State& state, + source_link_hash_t&& sourceLinkHash, + source_link_equality_t&& sourceLinkEquality) const; /// Updates the state iteratively by evicting one track after the other until /// the final state conditions are met. diff --git a/Core/include/Acts/AmbiguityResolution/GreedyAmbiguityResolution.ipp b/Core/include/Acts/AmbiguityResolution/GreedyAmbiguityResolution.ipp index 2f231ff216b..ec79c36260d 100644 --- a/Core/include/Acts/AmbiguityResolution/GreedyAmbiguityResolution.ipp +++ b/Core/include/Acts/AmbiguityResolution/GreedyAmbiguityResolution.ipp @@ -15,12 +15,11 @@ namespace Acts { -template class holder_t, typename source_link_hash_t, +template void GreedyAmbiguityResolution::computeInitialState( - const TrackContainer& tracks, - State& state, source_link_hash_t&& sourceLinkHash, + const track_container_t& tracks, State& state, + source_link_hash_t&& sourceLinkHash, source_link_equality_t&& sourceLinkEquality) const { auto measurementIndexMap = std::unordered_map class holder_t, bool ReadOnly = true> + template struct OptionalCuts { - using OptionalFilter = - std::function&)>; + using OptionalFilter = std::function; - using OptionalScoreModifier = std::function&, - double&)>; + using OptionalScoreModifier = + std::function; std::vector cuts = {}; std::vector weights = {}; @@ -146,12 +144,10 @@ class ScoreBasedAmbiguityResolution { /// @param sourceLinkEquality is the equality function for the source links /// @param trackFeaturesVectors is the trackFeatures map from detector ID to trackFeatures /// @return a vector of the initial state of the tracks - template class holder_t, typename source_link_hash_t, - typename source_link_equality_t> + template std::vector> computeInitialState( - const TrackContainer& tracks, - source_link_hash_t sourceLinkHash, + const track_container_t& tracks, source_link_hash_t sourceLinkHash, source_link_equality_t sourceLinkEquality, std::vector>& trackFeaturesVectors) const; @@ -161,12 +157,11 @@ class ScoreBasedAmbiguityResolution { /// @param trackFeaturesVectors is the trackFeatures map from detector ID to trackFeatures /// @param optionalCuts is the user defined optional cuts to be applied. /// @return a vector of scores for each track - template class holder_t, bool ReadOnly = true> + template std::vector simpleScore( - const TrackContainer& tracks, + const track_container_t& tracks, const std::vector>& trackFeaturesVectors, - const OptionalCuts& + const OptionalCuts& optionalCuts = {}) const; /// Compute the score of each track based on the ambiguity function. @@ -175,12 +170,11 @@ class ScoreBasedAmbiguityResolution { /// @param trackFeaturesVectors is the trackFeatures map from detector ID to trackFeatures /// @param optionalCuts is the user defined optional cuts to be applied. /// @return a vector of scores for each track - template class holder_t, bool ReadOnly = true> + template std::vector ambiguityScore( - const TrackContainer& tracks, + const track_container_t& tracks, const std::vector>& trackFeaturesVectors, - const OptionalCuts& + const OptionalCuts& optionalCuts = {}) const; /// Remove hits that are not good enough for each track and removes tracks @@ -205,13 +199,12 @@ class ScoreBasedAmbiguityResolution { /// @param trackFeaturesVectors is the map of detector id to trackFeatures for each track /// @param optionalCuts is the optional cuts to be applied /// @return a vector of IDs of the tracks we want to keep - template class holder_t, bool ReadOnly = true> + template std::vector solveAmbiguity( - const TrackContainer& tracks, + const track_container_t& tracks, const std::vector>& measurementsPerTrack, const std::vector>& trackFeaturesVectors, - const OptionalCuts& + const OptionalCuts& optionalCuts = {}) const; private: diff --git a/Core/include/Acts/AmbiguityResolution/ScoreBasedAmbiguityResolution.ipp b/Core/include/Acts/AmbiguityResolution/ScoreBasedAmbiguityResolution.ipp index 5175248a05c..8041188b5cf 100644 --- a/Core/include/Acts/AmbiguityResolution/ScoreBasedAmbiguityResolution.ipp +++ b/Core/include/Acts/AmbiguityResolution/ScoreBasedAmbiguityResolution.ipp @@ -10,6 +10,7 @@ #include "Acts/AmbiguityResolution/ScoreBasedAmbiguityResolution.hpp" #include "Acts/Definitions/Units.hpp" +#include "Acts/EventData/TrackContainerFrontendConcept.hpp" #include "Acts/Utilities/VectorHelpers.hpp" #include @@ -20,13 +21,11 @@ inline const Logger& ScoreBasedAmbiguityResolution::logger() const { return *m_logger; } -template class holder_t, typename source_link_hash_t, +template std::vector> ScoreBasedAmbiguityResolution::computeInitialState( - const TrackContainer& tracks, - source_link_hash_t sourceLinkHash, + const track_container_t& tracks, source_link_hash_t sourceLinkHash, source_link_equality_t sourceLinkEquality, std::vector>& trackFeaturesVectors) const { auto MeasurementIndexMap = @@ -98,12 +97,11 @@ ScoreBasedAmbiguityResolution::computeInitialState( return measurementsPerTrack; } -template class holder_t, bool ReadOnly> +template std::vector Acts::ScoreBasedAmbiguityResolution::simpleScore( - const TrackContainer& tracks, + const track_container_t& tracks, const std::vector>& trackFeaturesVectors, - const OptionalCuts& + const OptionalCuts& optionalCuts) const { std::vector trackScore; trackScore.reserve(tracks.size()); @@ -248,12 +246,11 @@ std::vector Acts::ScoreBasedAmbiguityResolution::simpleScore( return trackScore; } -template class holder_t, bool ReadOnly> +template std::vector Acts::ScoreBasedAmbiguityResolution::ambiguityScore( - const TrackContainer& tracks, + const track_container_t& tracks, const std::vector>& trackFeaturesVectors, - const OptionalCuts& + const OptionalCuts& optionalCuts) const { std::vector trackScore; trackScore.reserve(tracks.size()); @@ -425,13 +422,13 @@ std::vector Acts::ScoreBasedAmbiguityResolution::ambiguityScore( return trackScore; } -template class holder_t, bool ReadOnly> + +template std::vector Acts::ScoreBasedAmbiguityResolution::solveAmbiguity( - const TrackContainer& tracks, + const track_container_t& tracks, const std::vector>& measurementsPerTrack, const std::vector>& trackFeaturesVectors, - const OptionalCuts& + const OptionalCuts& optionalCuts) const { ACTS_INFO("Number of tracks before Ambiguty Resolution: " << tracks.size()); // vector of trackFeaturesVectors. where each trackFeaturesVector contains the diff --git a/Core/include/Acts/EventData/SubspaceHelpers.hpp b/Core/include/Acts/EventData/SubspaceHelpers.hpp index 8a27e7d7208..49a59e1dae7 100644 --- a/Core/include/Acts/EventData/SubspaceHelpers.hpp +++ b/Core/include/Acts/EventData/SubspaceHelpers.hpp @@ -39,7 +39,7 @@ inline static bool checkSubspaceIndices(const Container& container, if (subspaceSize > fullSize) { return false; } - if (container.size() != subspaceSize) { + if (static_cast(container.size()) != subspaceSize) { return false; } for (auto it = container.begin(); it != container.end();) { @@ -115,6 +115,36 @@ class SubspaceHelperBase { auto begin() const { return self().begin(); } auto end() const { return self().end(); } + bool contains(std::uint8_t index) const { + return std::find(begin(), end(), index) != end(); + } + std::size_t indexOf(std::uint8_t index) const { + auto it = std::find(begin(), end(), index); + return it != end() ? std::distance(begin(), it) : kFullSize; + } + + template + ActsVector expandVector( + const Eigen::DenseBase& vector) const { + ActsVector result = ActsVector::Zero(); + for (auto [i, index] : enumerate(*this)) { + result(index) = vector(i); + } + return result; + } + + template + FullSquareMatrix expandMatrix( + const Eigen::DenseBase& matrix) const { + FullSquareMatrix result = FullSquareMatrix::Zero(); + for (auto [i, indexI] : enumerate(*this)) { + for (auto [j, indexJ] : enumerate(*this)) { + result(indexI, indexJ) = matrix(i, j); + } + } + return result; + } + FullSquareMatrix fullProjector() const { FullSquareMatrix result = FullSquareMatrix::Zero(); for (auto [i, index] : enumerate(*this)) { @@ -168,6 +198,7 @@ class VariableSubspaceHelper bool empty() const { return m_indices.empty(); } std::size_t size() const { return m_indices.size(); } + const Container& indices() const { return m_indices; } IndexType operator[](std::size_t i) const { return m_indices[i]; } @@ -215,6 +246,7 @@ class FixedSubspaceHelper bool empty() const { return m_indices.empty(); } std::size_t size() const { return m_indices.size(); } + const Container& indices() const { return m_indices; } IndexType operator[](std::uint32_t i) const { return m_indices[i]; } diff --git a/Core/include/Acts/EventData/TrackContainerFrontendConcept.hpp b/Core/include/Acts/EventData/TrackContainerFrontendConcept.hpp new file mode 100644 index 00000000000..fdbb496ba9f --- /dev/null +++ b/Core/include/Acts/EventData/TrackContainerFrontendConcept.hpp @@ -0,0 +1,33 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 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 http://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/EventData/TrackContainerBackendConcept.hpp" +#include "Acts/EventData/Types.hpp" + +#include + +namespace Acts { + +template +concept TrackContainerFrontend = requires() { + { T::ReadOnly } -> std::same_as; + + requires std::same_as; + + requires TrackContainerBackend; + requires CommonMultiTrajectoryBackend; + + typename T::TrackProxy; + typename T::ConstTrackProxy; + typename T::TrackStateProxy; + typename T::ConstTrackStateProxy; +}; + +} // namespace Acts diff --git a/Core/include/Acts/EventData/TrackHelpers.hpp b/Core/include/Acts/EventData/TrackHelpers.hpp deleted file mode 100644 index f51e5428af0..00000000000 --- a/Core/include/Acts/EventData/TrackHelpers.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2023-2024 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 http://mozilla.org/MPL/2.0/. - -#pragma once - -// This header is deprecated and will be removed in the future. -// Please use the new header instead: -#include "Acts/Utilities/TrackHelpers.hpp" - -namespace Acts { - -// Funny header deprecation strategy -namespace { -[[deprecated( - "This header is deprecated - use " - "Acts/Utilities/TrackHelpers.hpp")]] constexpr static int - utilities_trackhelpers_hpp_is_deprecated = 0; -constexpr static int please_dont_use_utilities_trackhelpers_hpp = - utilities_trackhelpers_hpp_is_deprecated; -} // namespace - -} // namespace Acts diff --git a/Core/include/Acts/EventData/TrackProxy.hpp b/Core/include/Acts/EventData/TrackProxy.hpp index b60d6ca2a22..81bc0f41715 100644 --- a/Core/include/Acts/EventData/TrackProxy.hpp +++ b/Core/include/Acts/EventData/TrackProxy.hpp @@ -14,6 +14,7 @@ #include "Acts/EventData/ParticleHypothesis.hpp" #include "Acts/EventData/TrackContainerBackendConcept.hpp" #include "Acts/EventData/TrackParameters.hpp" +#include "Acts/EventData/TrackProxyConcept.hpp" #include "Acts/EventData/TrackStatePropMask.hpp" #include "Acts/Utilities/HashedString.hpp" #include "Acts/Utilities/UnitVectors.hpp" @@ -682,7 +683,7 @@ class TrackProxy { /// @tparam track_proxy_t the other track proxy's type /// @param other The track proxy /// @param copyTrackStates Copy the track state sequence from @p other - template + template void copyFrom(const track_proxy_t& other, bool copyTrackStates = true) requires(!ReadOnly) { @@ -710,6 +711,8 @@ class TrackProxy { setReferenceSurface(other.referenceSurface().getSharedPtr()); parameters() = other.parameters(); covariance() = other.covariance(); + } else { + setReferenceSurface(nullptr); } nMeasurements() = other.nMeasurements(); diff --git a/Core/include/Acts/EventData/TrackProxyConcept.hpp b/Core/include/Acts/EventData/TrackProxyConcept.hpp new file mode 100644 index 00000000000..619799905e4 --- /dev/null +++ b/Core/include/Acts/EventData/TrackProxyConcept.hpp @@ -0,0 +1,30 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 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 http://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/EventData/MultiTrajectoryBackendConcept.hpp" +#include "Acts/EventData/TrackContainerBackendConcept.hpp" +#include "Acts/EventData/Types.hpp" + +#include + +namespace Acts { + +template +concept TrackProxyConcept = requires() { + { T::ReadOnly } -> std::same_as; + + requires TrackContainerBackend; + + requires CommonMultiTrajectoryBackend; + + requires std::same_as; +}; + +} // namespace Acts diff --git a/Core/include/Acts/Material/HomogeneousSurfaceMaterial.hpp b/Core/include/Acts/Material/HomogeneousSurfaceMaterial.hpp index 01a1e2702a0..541bbaeca1e 100644 --- a/Core/include/Acts/Material/HomogeneousSurfaceMaterial.hpp +++ b/Core/include/Acts/Material/HomogeneousSurfaceMaterial.hpp @@ -78,7 +78,8 @@ class HomogeneousSurfaceMaterial : public ISurfaceMaterial { /// @copydoc ISurfaceMaterial::materialSlab(const Vector3&) const /// /// @note the input parameter is ignored - const MaterialSlab& materialSlab(const Vector3& gp) const final; + const MaterialSlab& materialSlab(const Vector3& gp = Vector3{0., 0., + 0.}) const final; /// The inherited methods - for MaterialSlab access using ISurfaceMaterial::materialSlab; diff --git a/Core/include/Acts/Propagator/Navigator.hpp b/Core/include/Acts/Propagator/Navigator.hpp index 116214fe95d..73e928b762e 100644 --- a/Core/include/Acts/Propagator/Navigator.hpp +++ b/Core/include/Acts/Propagator/Navigator.hpp @@ -276,24 +276,6 @@ class Navigator { m_cfg.trackingGeometry->highestTrackingVolume(); } - // We set the current surface to the start surface - // for eventual post-update action, e.g. material integration - // or collection when leaving a surface at the start of - // an extrapolation process - state.navigation.currentSurface = state.navigation.startSurface; - if (state.navigation.currentSurface != nullptr) { - ACTS_VERBOSE(volInfo(state) - << "Current surface set to start surface " - << state.navigation.currentSurface->geometryId()); - - assert(state.navigation.currentSurface->isOnSurface( - state.geoContext, stepper.position(state.stepping), - stepper.direction(state.stepping), - BoundaryTolerance::Infinite(), - state.options.surfaceTolerance) && - "Stepper not on surface"); - } - // Fast Navigation initialization for start condition: // - short-cut through object association, saves navigation in the // - geometry and volume tree search for the lowest volume @@ -302,18 +284,26 @@ class Navigator { ACTS_VERBOSE( volInfo(state) << "Fast start initialization through association from Surface."); + // assign the current layer and volume by association state.navigation.startLayer = state.navigation.startSurface->associatedLayer(); + state.navigation.currentLayer = state.navigation.startLayer; + state.navigation.startVolume = state.navigation.startLayer->trackingVolume(); + state.navigation.currentVolume = state.navigation.startVolume; } else if (state.navigation.startVolume != nullptr) { ACTS_VERBOSE( volInfo(state) << "Fast start initialization through association from Volume."); + + state.navigation.currentVolume = state.navigation.startVolume; + state.navigation.startLayer = state.navigation.startVolume->associatedLayer( state.geoContext, stepper.position(state.stepping)); + state.navigation.currentLayer = state.navigation.startLayer; } else { ACTS_VERBOSE(volInfo(state) << "Slow start initialization through search."); @@ -323,15 +313,17 @@ class Navigator { << toString(stepper.position(state.stepping)) << " and direction " << toString(stepper.direction(state.stepping))); + state.navigation.startVolume = m_cfg.trackingGeometry->lowestTrackingVolume( state.geoContext, stepper.position(state.stepping)); - state.navigation.startLayer = - state.navigation.startVolume != nullptr - ? state.navigation.startVolume->associatedLayer( - state.geoContext, stepper.position(state.stepping)) - : nullptr; + state.navigation.currentVolume = state.navigation.startVolume; + if (state.navigation.startVolume != nullptr) { + state.navigation.startLayer = + state.navigation.startVolume->associatedLayer( + state.geoContext, stepper.position(state.stepping)); + state.navigation.currentLayer = state.navigation.startLayer; ACTS_VERBOSE(volInfo(state) << "Start volume resolved."); } else { ACTS_VERBOSE(volInfo(state) @@ -341,15 +333,41 @@ class Navigator { } } + if (state.navigation.startVolume != nullptr) { + ACTS_VERBOSE(volInfo(state) << "Start volume resolved."); + assert(state.navigation.startVolume->inside( + stepper.position(state.stepping), + state.options.surfaceTolerance) && + "We did not end up inside the volume."); + } + + if (state.navigation.startLayer != nullptr) { + ACTS_VERBOSE(volInfo(state) << "Start layer resolved " + << state.navigation.startLayer->geometryId()); + // We provide the layer to the resolve surface method in this case + resolveSurfaces(state, stepper); + } + // Set the start volume as current volume state.navigation.currentVolume = state.navigation.startVolume; // Set the start layer as current layer state.navigation.currentLayer = state.navigation.startLayer; - if (state.navigation.startLayer != nullptr) { - ACTS_VERBOSE(volInfo(state) << "Start layer to be resolved."); - // We provide the layer to the resolve surface method in this case - resolveSurfaces(state, stepper); + // We set the current surface to the start surface for eventual post-update + // action, e.g. material integration or collection when leaving a surface at + // the start of an extrapolation process + state.navigation.currentSurface = state.navigation.startSurface; + if (state.navigation.currentSurface != nullptr) { + ACTS_VERBOSE(volInfo(state) + << "Current surface set to start surface " + << state.navigation.currentSurface->geometryId()); + + assert(state.navigation.currentSurface->isOnSurface( + state.geoContext, stepper.position(state.stepping), + stepper.direction(state.stepping), + BoundaryTolerance::Infinite(), + state.options.surfaceTolerance) && + "Stepper not on surface"); } } @@ -551,6 +569,10 @@ class Navigator { return; } else { ACTS_VERBOSE(volInfo(state) << "Volume updated."); + assert(state.navigation.currentVolume->inside( + stepper.position(state.stepping), + state.options.surfaceTolerance) && + "We did not end up inside the volume."); // Forget the boundary information state.navigation.navBoundaries.clear(); state.navigation.navBoundaryIndex = diff --git a/Core/include/Acts/TrackFinding/TrackSelector.hpp b/Core/include/Acts/TrackFinding/TrackSelector.hpp index 3849b4a9dc5..0695bf08a8b 100644 --- a/Core/include/Acts/TrackFinding/TrackSelector.hpp +++ b/Core/include/Acts/TrackFinding/TrackSelector.hpp @@ -8,6 +8,7 @@ #pragma once +#include "Acts/EventData/TrackProxyConcept.hpp" #include "Acts/EventData/TrackStateType.hpp" #include "Acts/Geometry/GeometryHierarchyMap.hpp" #include "Acts/Geometry/GeometryIdentifier.hpp" @@ -37,7 +38,7 @@ class TrackSelector { boost::container::small_vector counters; - template + template bool isValidTrack(const track_proxy_t& track) const; void addCounter(const std::vector& identifiers, @@ -227,7 +228,7 @@ class TrackSelector { /// @tparam track_proxy_t is the type of the track proxy /// @param track is the track proxy /// @return true if the track is valid - template + template bool isValidTrack(const track_proxy_t& track) const; /// Get readonly access to the config parameters @@ -389,7 +390,7 @@ void TrackSelector::selectTracks(const input_tracks_t& inputTracks, } } -template +template bool TrackSelector::isValidTrack(const track_proxy_t& track) const { auto checkMin = [](auto x, auto min) { return min <= x; }; auto checkMax = [](auto x, auto max) { return x <= max; }; @@ -478,7 +479,7 @@ inline TrackSelector::TrackSelector( inline TrackSelector::TrackSelector(const Config& config) : TrackSelector{EtaBinnedConfig{config}} {} -template +template bool TrackSelector::MeasurementCounter::isValidTrack( const track_proxy_t& track) const { // No hit cuts, accept everything diff --git a/Core/include/Acts/TrackFitting/GaussianSumFitter.hpp b/Core/include/Acts/TrackFitting/GaussianSumFitter.hpp index 0b1f9d5e78d..ada401ba401 100644 --- a/Core/include/Acts/TrackFitting/GaussianSumFitter.hpp +++ b/Core/include/Acts/TrackFitting/GaussianSumFitter.hpp @@ -91,13 +91,12 @@ struct GaussianSumFitter { /// @brief The fit function for the Direct navigator template class holder_t> + TrackContainerFrontend track_container_t> auto fit(source_link_it_t begin, source_link_it_t end, const start_parameters_t& sParameters, const GsfOptions& options, const std::vector& sSequence, - TrackContainer& trackContainer) - const { + track_container_t& trackContainer) const { // Check if we have the correct navigator static_assert( std::is_same_v); @@ -148,12 +147,11 @@ struct GaussianSumFitter { /// @brief The fit function for the standard navigator template class holder_t> + TrackContainerFrontend track_container_t> auto fit(source_link_it_t begin, source_link_it_t end, const start_parameters_t& sParameters, const GsfOptions& options, - TrackContainer& trackContainer) - const { + track_container_t& trackContainer) const { // Check if we have the correct navigator static_assert(std::is_same_v); @@ -200,16 +198,13 @@ struct GaussianSumFitter { /// first measurementSurface template class holder_t> - Acts::Result< - typename TrackContainer::TrackProxy> - fit_impl(source_link_it_t begin, source_link_it_t end, - const start_parameters_t& sParameters, - const GsfOptions& options, - const fwd_prop_initializer_t& fwdPropInitializer, - const bwd_prop_initializer_t& bwdPropInitializer, - TrackContainer& trackContainer) - const { + TrackContainerFrontend track_container_t> + Acts::Result fit_impl( + source_link_it_t begin, source_link_it_t end, + const start_parameters_t& sParameters, const GsfOptions& options, + const fwd_prop_initializer_t& fwdPropInitializer, + const bwd_prop_initializer_t& bwdPropInitializer, + track_container_t& trackContainer) const { // return or abort utility auto return_error_or_abort = [&](auto error) { if (options.abortOnError) { diff --git a/Core/include/Acts/TrackFitting/GlobalChiSquareFitter.hpp b/Core/include/Acts/TrackFitting/GlobalChiSquareFitter.hpp index e84226ca393..e87a52410d8 100644 --- a/Core/include/Acts/TrackFitting/GlobalChiSquareFitter.hpp +++ b/Core/include/Acts/TrackFitting/GlobalChiSquareFitter.hpp @@ -16,6 +16,7 @@ #include "Acts/EventData/MultiTrajectory.hpp" #include "Acts/EventData/MultiTrajectoryHelpers.hpp" #include "Acts/EventData/SourceLink.hpp" +#include "Acts/EventData/TrackContainerFrontendConcept.hpp" #include "Acts/EventData/TrackParameters.hpp" #include "Acts/EventData/VectorMultiTrajectory.hpp" #include "Acts/EventData/VectorTrackContainer.hpp" @@ -52,8 +53,8 @@ namespace Acts::Experimental { namespace Gx2fConstants { constexpr std::string_view gx2fnUpdateColumn = "Gx2fnUpdateColumn"; -// Mask for the track states. We don't need Smoothed and Filtered -constexpr TrackStatePropMask trackStateMask = TrackStatePropMask::Predicted | +// Mask for the track states. We don't need Predicted and Filtered +constexpr TrackStatePropMask trackStateMask = TrackStatePropMask::Smoothed | TrackStatePropMask::Jacobian | TrackStatePropMask::Calibrated; @@ -343,7 +344,7 @@ void addMeasurementToGx2fSums(Eigen::MatrixXd& aMatrixExtended, extendedJacobian.block(0, deltaPosition) = jacPhiTheta; } - const BoundVector predicted = trackState.predicted(); + const BoundVector predicted = trackState.smoothed(); const ActsVector measurement = trackState.template calibrated(); @@ -431,7 +432,7 @@ void addMaterialToGx2fSums( "No scattering angles found for material surface."); } - const ActsScalar sinThetaLoc = std::sin(trackState.predicted()[eBoundTheta]); + const ActsScalar sinThetaLoc = std::sin(trackState.smoothed()[eBoundTheta]); // The position, where we need to insert the values in aMatrix and bVector const std::size_t deltaPosition = eBoundSize + 2 * nMaterialsHandled; @@ -497,9 +498,9 @@ void addMaterialToGx2fSums( /// @param ndfSystem The number of degrees of freedom, determining the size of meaning full block /// /// @return deltaParams The calculated delta parameters. -void updateCovariancePredicted(BoundMatrix& fullCovariancePredicted, - Eigen::MatrixXd& aMatrixExtended, - const std::size_t ndfSystem); +void updateGx2fCovarianceParams(BoundMatrix& fullCovariancePredicted, + Eigen::MatrixXd& aMatrixExtended, + const std::size_t ndfSystem); /// Global Chi Square fitter (GX2F) implementation. /// @@ -736,8 +737,8 @@ class Gx2Fitter { } // Fill the track state - trackStateProxy.predicted() = boundParams.parameters(); - trackStateProxy.predictedCovariance() = state.stepping.cov; + trackStateProxy.smoothed() = boundParams.parameters(); + trackStateProxy.smoothedCovariance() = state.stepping.cov; trackStateProxy.jacobian() = jacobian; trackStateProxy.pathLength() = pathLength; @@ -746,13 +747,13 @@ class Gx2Fitter { stepper.update(state.stepping, transformBoundToFreeParameters( trackStateProxy.referenceSurface(), - state.geoContext, trackStateProxy.predicted()), - trackStateProxy.predicted(), - trackStateProxy.predictedCovariance(), *surface); + state.geoContext, trackStateProxy.smoothed()), + trackStateProxy.smoothed(), + trackStateProxy.smoothedCovariance(), *surface); } } - // We have predicted parameters, so calibrate the uncalibrated input + // We have smoothed parameters, so calibrate the uncalibrated input // measurement extensions.calibrator(state.geoContext, *calibrationContext, sourcelink_it->second, trackStateProxy); @@ -837,8 +838,8 @@ class Gx2Fitter { ACTS_VERBOSE(" boundParams after the update:\n" << boundParams); // Fill the track state - trackStateProxy.predicted() = boundParams.parameters(); - trackStateProxy.predictedCovariance() = state.stepping.cov; + trackStateProxy.smoothed() = boundParams.parameters(); + trackStateProxy.smoothedCovariance() = state.stepping.cov; trackStateProxy.jacobian() = jacobian; trackStateProxy.pathLength() = pathLength; @@ -846,9 +847,9 @@ class Gx2Fitter { stepper.update(state.stepping, transformBoundToFreeParameters( trackStateProxy.referenceSurface(), - state.geoContext, trackStateProxy.predicted()), - trackStateProxy.predicted(), - trackStateProxy.predictedCovariance(), *surface); + state.geoContext, trackStateProxy.smoothed()), + trackStateProxy.smoothed(), + trackStateProxy.smoothedCovariance(), *surface); } // Get and set the type flags @@ -921,8 +922,8 @@ class Gx2Fitter { const auto& [boundParams, jacobian, pathLength] = *res; // Fill the track state - trackStateProxy.predicted() = boundParams.parameters(); - trackStateProxy.predictedCovariance() = state.stepping.cov; + trackStateProxy.smoothed() = boundParams.parameters(); + trackStateProxy.smoothedCovariance() = state.stepping.cov; trackStateProxy.jacobian() = jacobian; trackStateProxy.pathLength() = pathLength; @@ -996,13 +997,12 @@ class Gx2Fitter { /// @return the output as an output track template class holder_t> - auto fit(source_link_iterator_t it, source_link_iterator_t end, - const start_parameters_t& sParameters, - const Gx2FitterOptions& gx2fOptions, - TrackContainer& trackContainer) - const -> Result::TrackProxy> + TrackContainerFrontend track_container_t> + Result fit( + source_link_iterator_t it, source_link_iterator_t end, + const start_parameters_t& sParameters, + const Gx2FitterOptions& gx2fOptions, + track_container_t& trackContainer) const requires(!isDirectNavigator) { // Preprocess Measurements (SourceLinks -> map) @@ -1046,7 +1046,7 @@ class Gx2Fitter { // new track and delete it after updating the parameters. However, if we // would work on the externally provided track container, it would be // difficult to remove the correct track, if it contains more than one. - track_container_t trackContainerTempBackend; + typename track_container_t::TrackContainerBackend trackContainerTempBackend; traj_t trajectoryTempBackend; TrackContainer trackContainerTemp{trackContainerTempBackend, trajectoryTempBackend}; @@ -1334,16 +1334,16 @@ class Gx2Fitter { ACTS_INFO("Abort with relChi2changeCutOff after " << nUpdate + 1 << "/" << gx2fOptions.nUpdateMax << " iterations."); - updateCovariancePredicted(fullCovariancePredicted, aMatrixExtended, - ndfSystem); + updateGx2fCovarianceParams(fullCovariancePredicted, aMatrixExtended, + ndfSystem); break; } if (chi2sum > oldChi2sum + 1e-5) { ACTS_DEBUG("chi2 not converging monotonically"); - updateCovariancePredicted(fullCovariancePredicted, aMatrixExtended, - ndfSystem); + updateGx2fCovarianceParams(fullCovariancePredicted, aMatrixExtended, + ndfSystem); break; } @@ -1361,8 +1361,8 @@ class Gx2Fitter { return Experimental::GlobalChiSquareFitterError::DidNotConverge; } - updateCovariancePredicted(fullCovariancePredicted, aMatrixExtended, - ndfSystem); + updateGx2fCovarianceParams(fullCovariancePredicted, aMatrixExtended, + ndfSystem); break; } diff --git a/Core/include/Acts/TrackFitting/KalmanFitter.hpp b/Core/include/Acts/TrackFitting/KalmanFitter.hpp index f5e2a10e7ff..7e7001d00ad 100644 --- a/Core/include/Acts/TrackFitting/KalmanFitter.hpp +++ b/Core/include/Acts/TrackFitting/KalmanFitter.hpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2016-2023 CERN for the benefit of the Acts project +// Copyright (C) 2016-2024 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 @@ -14,6 +14,7 @@ #include "Acts/EventData/MultiTrajectory.hpp" #include "Acts/EventData/MultiTrajectoryHelpers.hpp" #include "Acts/EventData/SourceLink.hpp" +#include "Acts/EventData/TrackContainerFrontendConcept.hpp" #include "Acts/EventData/TrackParameters.hpp" #include "Acts/EventData/VectorMultiTrajectory.hpp" #include "Acts/Geometry/GeometryContext.hpp" @@ -1067,8 +1068,7 @@ class KalmanFitter { /// @tparam source_link_iterator_t Iterator type used to pass source links /// @tparam start_parameters_t Type of the initial parameters /// @tparam parameters_t Type of parameters used for local parameters - /// @tparam track_container_t Type of the track container backend - /// @tparam holder_t Type defining track container backend ownership + /// @tparam track_container_t Type of the track container /// /// @param it Begin iterator for the fittable uncalibrated measurements /// @param end End iterator for the fittable uncalibrated measurements @@ -1082,13 +1082,12 @@ class KalmanFitter { /// @return the output as an output track template class holder_t> - auto fit(source_link_iterator_t it, source_link_iterator_t end, - const start_parameters_t& sParameters, - const KalmanFitterOptions& kfOptions, - TrackContainer& trackContainer) - const -> Result::TrackProxy> + TrackContainerFrontend track_container_t> + Result fit( + source_link_iterator_t it, source_link_iterator_t end, + const start_parameters_t& sParameters, + const KalmanFitterOptions& kfOptions, + track_container_t& trackContainer) const requires(!isDirectNavigator) { // To be able to find measurements later, we put them into a map @@ -1145,8 +1144,8 @@ class KalmanFitter { kalmanActor.actorLogger = m_actorLogger.get(); return fit_impl(sParameters, propagatorOptions, - trackContainer); + track_container_t>(sParameters, propagatorOptions, + trackContainer); } /// Fit implementation of the forward filter, calls the @@ -1155,8 +1154,7 @@ class KalmanFitter { /// @tparam source_link_iterator_t Iterator type used to pass source links /// @tparam start_parameters_t Type of the initial parameters /// @tparam parameters_t Type of parameters used for local parameters - /// @tparam track_container_t Type of the track container backend - /// @tparam holder_t Type defining track container backend ownership + /// @tparam track_container_t Type of the track container /// /// @param it Begin iterator for the fittable uncalibrated measurements /// @param end End iterator for the fittable uncalibrated measurements @@ -1172,14 +1170,13 @@ class KalmanFitter { /// @return the output as an output track template class holder_t> - auto fit(source_link_iterator_t it, source_link_iterator_t end, - const start_parameters_t& sParameters, - const KalmanFitterOptions& kfOptions, - const std::vector& sSequence, - TrackContainer& trackContainer) - const -> Result::TrackProxy> + TrackContainerFrontend track_container_t> + Result fit( + source_link_iterator_t it, source_link_iterator_t end, + const start_parameters_t& sParameters, + const KalmanFitterOptions& kfOptions, + const std::vector& sSequence, + track_container_t& trackContainer) const requires(isDirectNavigator) { // To be able to find measurements later, we put them into a map @@ -1230,8 +1227,8 @@ class KalmanFitter { propagatorOptions.navigation.surfaces = sSequence; return fit_impl(sParameters, propagatorOptions, - trackContainer); + track_container_t>(sParameters, propagatorOptions, + trackContainer); } private: @@ -1241,8 +1238,7 @@ class KalmanFitter { /// @tparam actor_list_t Type of the actor list /// @tparam aborter_list_t Type of the abort list /// @tparam kalman_result_t Type of the KF result - /// @tparam track_container_t Type of the track container backend - /// @tparam holder_t Type defining track container backend ownership + /// @tparam track_container_t Type of the track container /// /// @param sParameters The initial track parameters /// @param propagatorOptions The Propagator Options @@ -1250,14 +1246,11 @@ class KalmanFitter { /// /// @return the output as an output track template class holder_t> - auto fit_impl( - const start_parameters_t& sParameters, - const propagator_options_t& propagatorOptions, - TrackContainer& trackContainer) const - -> Result::TrackProxy> { + typename kalman_result_t, TrackContainerFrontend track_container_t> + auto fit_impl(const start_parameters_t& sParameters, + const propagator_options_t& propagatorOptions, + track_container_t& trackContainer) const + -> Result { auto propagatorState = m_propagator.template makeState(sParameters, propagatorOptions); diff --git a/Core/include/Acts/Utilities/TrackHelpers.hpp b/Core/include/Acts/Utilities/TrackHelpers.hpp index 2fe845f6c39..11589981b9b 100644 --- a/Core/include/Acts/Utilities/TrackHelpers.hpp +++ b/Core/include/Acts/Utilities/TrackHelpers.hpp @@ -10,7 +10,9 @@ #include "Acts/Definitions/Tolerance.hpp" #include "Acts/EventData/MultiTrajectoryHelpers.hpp" +#include "Acts/EventData/TrackContainerFrontendConcept.hpp" #include "Acts/EventData/TrackParameters.hpp" +#include "Acts/EventData/TrackProxyConcept.hpp" #include "Acts/EventData/TrackStateType.hpp" #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Propagator/StandardAborters.hpp" @@ -40,7 +42,7 @@ enum class TrackExtrapolationError { std::error_code make_error_code(TrackExtrapolationError e); -template +template Result findFirstMeasurementState( const track_proxy_t &track) { using TrackStateProxy = typename track_proxy_t::ConstTrackStateProxy; @@ -63,7 +65,7 @@ Result findFirstMeasurementState( return result; } -template +template Result findLastMeasurementState( const track_proxy_t &track) { using TrackStateProxy = typename track_proxy_t::ConstTrackStateProxy; @@ -93,7 +95,8 @@ Result findLastMeasurementState( /// @param smoother The smoother /// /// @return The result of the smoothing -template +template Result smoothTrack( const GeometryContext &geoContext, track_proxy_t &track, const Logger &logger = *getDefaultLogger("TrackSmoother", Logging::INFO), @@ -128,7 +131,7 @@ Result smoothTrack( /// @param logger The logger /// /// @return The result of the smoothing -template +template Result smoothTracks( const GeometryContext &geoContext, const track_container_t &trackContainer, const Logger &logger = *getDefaultLogger("TrackSmoother", Logging::INFO)) { @@ -158,7 +161,7 @@ Result smoothTracks( /// /// @return The result of the search containing the track state /// and the distance to the reference surface -template +template Result> findTrackStateForExtrapolation( const GeometryContext &geoContext, const track_proxy_t &track, @@ -283,7 +286,7 @@ findTrackStateForExtrapolation( /// @param logger The logger /// /// @return The result of the extrapolation -template Result extrapolateTrackToReferenceSurface( track_proxy_t &track, const Surface &referenceSurface, @@ -340,7 +343,7 @@ Result extrapolateTrackToReferenceSurface( /// @param logger The logger /// /// @return The result of the extrapolation -template Result extrapolateTracksToReferenceSurface( const track_container_t &trackContainer, const Surface &referenceSurface, @@ -370,12 +373,8 @@ Result extrapolateTracksToReferenceSurface( /// @tparam track_state_container_t the track state container backend /// @tparam holder_t the holder type for the track container backends /// @param track A mutable track proxy to operate on -template class holder_t> -void calculateTrackQuantities( - Acts::TrackProxy - track) { +template +void calculateTrackQuantities(track_proxy_t track) { track.chi2() = 0; track.nDoF() = 0; diff --git a/Core/include/Acts/Utilities/detail/Subspace.hpp b/Core/include/Acts/Utilities/detail/Subspace.hpp deleted file mode 100644 index fe355b44edb..00000000000 --- a/Core/include/Acts/Utilities/detail/Subspace.hpp +++ /dev/null @@ -1,327 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2020 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 http://mozilla.org/MPL/2.0/. - -#pragma once - -#include "Acts/Definitions/Algebra.hpp" - -#include -#include -#include -#include - -namespace Acts::detail { - -/// @defgroup subspace Linear subspace definitions -/// -/// All types in this group define a linear subspace of a larger vector space -/// with the following properties: the subspace is defined by a set of axis -/// indices in the full space, i.e. there is no need for a non-trivial -/// projection matrix, all subspace axis indices are unique and there are no -/// duplicated ones, and the set of axis indices must be ordered, i.e. the axis -/// order in the subspace is the same as in the full space. The last requirement -/// is not strictly required by the implementation, but is still added to -/// simplify reasoning. -/// -/// Only the size of the subspace are defined by the types at compile time. -/// Which axes comprise the subspace is defined at runtime. This allows to use -/// fixed-size computations (selected at compile time) but avoids the -/// combinatorial explosion of also having to handle all possible combination of -/// axes at compile time. This was tried previously and resulted in sizable -/// resource consumption at compile time without runtime benefits. -/// -/// All types are intentionally using `std::size_t` as their template values, -/// instead of the more specific index enums, to reduce the number of templates. -/// This is fully compatible as the index enums are required to be convertible -/// to `std::size_t`. -/// -/// All types intentionally only define the subspace but not how vectors -/// and matrices are stored to avoid unnecessary coupling between components, -/// i.e here between the pure definition and the storage. -/// -/// All types provide `.projectVector(...)` and `.exandVector(...)` methods to -/// convert to/from the subspace. They also provide `.projector()` and -/// `.expander()` methods to create projection and expansion matrices if they -/// are required explicitly. For the specific subspace requirements listed -/// above, the projection and expansion matrices are transpose to each other. In -/// the general case, this does not have to be the case and users are encouraged -/// to use `.projector()` and `.expander()` instead of e.g. -/// `.projector().transpose()`. -/// -/// @{ - -/// Fixed-size subspace representation. -/// -/// @tparam kFullSize Size of the full vector space -/// @tparam kSize Size of the subspace -template -class FixedSizeSubspace { - static_assert(kFullSize <= static_cast( - std::numeric_limits::max()), - "Full vector space size is larger than the supported range"); - static_assert(1u <= kSize, "Subspace size must be at least 1"); - static_assert(kSize <= kFullSize, - "Subspace can only be as large as the full space"); - - template - using SubspaceVectorFor = Eigen::Matrix; - template - using FullspaceVectorFor = - Eigen::Matrix; - template - using ProjectionMatrix = Eigen::Matrix; - template - using ExpansionMatrix = Eigen::Matrix; - - // the functionality could also be implemented using a std::bitset where each - // bit corresponds to an axis in the fullspace and set bits indicate which - // bits make up the subspace. this would be a more compact representation but - // complicates the implementation since we can not easily iterate over the - // indices of the subspace. storing the subspace indices directly requires a - // bit more memory but is easier to work with. for our typical use cases with - // n<=8, this still takes only 64bit of memory. - std::array m_axes; - - public: - /// Construct from a container of axis indices. - /// - /// @tparam index_t Input index type, must be convertible to std::uint8_t - /// @param indices Unique, ordered indices - template - constexpr explicit FixedSizeSubspace( - const std::array& indices) { - for (std::size_t i = 0u; i < kSize; ++i) { - assert((indices[i] < kFullSize) && - "Axis indices must be within the full space"); - if (0u < i) { - assert((indices[i - 1u] < indices[i]) && - "Axis indices must be unique and ordered"); - } - } - for (std::size_t i = 0; i < kSize; ++i) { - m_axes[i] = static_cast(indices[i]); - } - } - - /// Size of the subspace. - static constexpr std::size_t size() { return kSize; } - /// Size of the full vector space. - static constexpr std::size_t fullSize() { return kFullSize; } - - /// Access axis index by position. - /// - /// @param i Position in the subspace - /// @return Axis index in the full space - constexpr std::size_t operator[](std::size_t i) const { return m_axes[i]; } - - std::size_t indexOf(std::size_t axis) const { - for (std::size_t i = 0; i < kSize; ++i) { - if (m_axes[i] == axis) { - return i; - } - } - return kSize; - } - - /// Axis indices that comprise the subspace. - /// - /// The specific container and index type should be considered an - /// implementation detail. Users should treat the return type as a generic - /// container whose elements are convertible to `std::size_t`. - constexpr const std::array& indices() const { - return m_axes; - } - - /// Check if the given axis index in the full space is part of the subspace. - constexpr bool contains(std::size_t index) const { - bool isContained = false; - // always iterate over all elements to avoid branching and hope the compiler - // can optimise this for us. - for (std::uint8_t a : m_axes) { - isContained = isContained || (a == index); - } - return isContained; - } - - /// Project a full vector into the subspace. - /// - /// @tparam fullspace_vector_t Vector type in the full space - /// @param full Vector in the full space - /// @return Subspace vector w/ just the configured axis components - /// - /// @note Always returns a column vector regardless of the input - template - SubspaceVectorFor projectVector( - const Eigen::MatrixBase& full) const { - EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(fullspace_vector_t, kFullSize); - - SubspaceVectorFor sub; - for (std::size_t i = 0u; i < kSize; ++i) { - sub[i] = full[m_axes[i]]; - } - return sub; - } - - /// Expand a subspace vector into the full space. - /// - /// @tparam subspace_vector_t Subspace vector type - /// @param sub Subspace vector - /// @return Vector in the full space w/ zeros for non-subspace components - /// - /// @note Always returns a column vector regardless of the input - template - FullspaceVectorFor expandVector( - const Eigen::MatrixBase& sub) const { - EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(subspace_vector_t, kSize); - - FullspaceVectorFor full; - full.setZero(); - for (std::size_t i = 0u; i < kSize; ++i) { - full[m_axes[i]] = sub[i]; - } - return full; - } - - /// Projection matrix that maps from the full space into the subspace. - /// - /// @tparam scalar_t Scalar type for the projection matrix - template - ProjectionMatrix projector() const { - ProjectionMatrix proj; - proj.setZero(); - for (std::size_t i = 0u; i < kSize; ++i) { - proj(i, m_axes[i]) = 1; - } - return proj; - } - - /// Expansion matrix that maps from the subspace into the full space. - /// - /// @tparam scalar_t Scalar type of the generated expansion matrix - template - ExpansionMatrix expander() const { - ExpansionMatrix expn; - expn.setZero(); - for (std::size_t i = 0u; i < kSize; ++i) { - expn(m_axes[i], i) = 1; - } - return expn; - } -}; - -/// Variable-size subspace representation. -/// -/// @tparam kFullSize Size of the full vector space -/// @tparam kSize Size of the subspace -template -class VariableSizeSubspace { - static_assert(kFullSize <= static_cast(UINT8_MAX), - "Full vector space size is larger than the supported range"); - - template - using FullProjectionMatrix = Eigen::Matrix; - template - using FullExpansionMatrix = Eigen::Matrix; - - std::size_t m_size{}; - - // the functionality could also be implemented using a std::bitset where each - // bit corresponds to an axis in the fullspace and set bits indicate which - // bits make up the subspace. this would be a more compact representation but - // complicates the implementation since we can not easily iterate over the - // indices of the subspace. storing the subspace indices directly requires a - // bit more memory but is easier to work with. for our typical use cases with - // n<=8, this still takes only 64bit of memory. - std::array m_axes{}; - - public: - /// Construct from a container of axis indices. - /// - /// @tparam index_t Input index type, must be convertible to std::uint8_t - /// @param indices Unique, ordered indices - template - constexpr explicit VariableSizeSubspace( - const std::array& indices) { - m_size = kSize; - for (std::size_t i = 0u; i < kSize; ++i) { - assert((indices[i] < kFullSize) && - "Axis indices must be within the full space"); - if (0u < i) { - assert((indices[i - 1u] < indices[i]) && - "Axis indices must be unique and ordered"); - } - } - for (std::size_t i = 0; i < kSize; ++i) { - m_axes[i] = static_cast(indices[i]); - } - } - - /// Size of the subspace. - constexpr std::size_t size() const { return m_size; } - /// Size of the full vector space. - static constexpr std::size_t fullSize() { return kFullSize; } - - /// Access axis index by position. - /// - /// @param i Position in the subspace - /// @return Axis index in the full space - constexpr std::size_t operator[](std::size_t i) const { - assert(i < m_size); - return m_axes[i]; - } - - std::size_t indexOf(std::size_t axis) const { - for (std::size_t i = 0; i < m_size; ++i) { - if (m_axes[i] == axis) { - return i; - } - } - return m_size; - } - - /// Check if the given axis index in the full space is part of the subspace. - constexpr bool contains(std::size_t index) const { - bool isContained = false; - // always iterate over all elements to avoid branching and hope the compiler - // can optimise this for us. - for (std::size_t i = 0; i < kFullSize; ++i) { - isContained = isContained || ((i < m_size) && (m_axes[i] == index)); - } - return isContained; - } - - /// Projection matrix that maps from the full space into the subspace. - /// - /// @tparam scalar_t Scalar type for the projection matrix - template - FullProjectionMatrix fullProjector() const { - FullProjectionMatrix proj; - proj.setZero(); - for (std::size_t i = 0u; i < m_size; ++i) { - proj(i, m_axes[i]) = 1; - } - return proj; - } - - /// Expansion matrix that maps from the subspace into the full space. - /// - /// @tparam scalar_t Scalar type of the generated expansion matrix - template - FullExpansionMatrix fullExpander() const { - FullExpansionMatrix expn; - expn.setZero(); - for (std::size_t i = 0u; i < m_size; ++i) { - expn(m_axes[i], i) = 1; - } - return expn; - } -}; - -/// @} - -} // namespace Acts::detail diff --git a/Core/src/TrackFitting/GlobalChiSquareFitter.cpp b/Core/src/TrackFitting/GlobalChiSquareFitter.cpp index 029be0719f4..0bbde3c0100 100644 --- a/Core/src/TrackFitting/GlobalChiSquareFitter.cpp +++ b/Core/src/TrackFitting/GlobalChiSquareFitter.cpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2023 CERN for the benefit of the Acts project +// Copyright (C) 2023-2024 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 @@ -10,11 +10,9 @@ #include "Acts/Definitions/TrackParametrization.hpp" -namespace Acts::Experimental { - -void updateCovariancePredicted(BoundMatrix& fullCovariancePredicted, - Eigen::MatrixXd& aMatrixExtended, - const std::size_t ndfSystem) { +void Acts::Experimental::updateGx2fCovarianceParams( + BoundMatrix& fullCovariancePredicted, Eigen::MatrixXd& aMatrixExtended, + const std::size_t ndfSystem) { // make invertible for (int i = 0; i < aMatrixExtended.rows(); ++i) { if (aMatrixExtended(i, i) == 0.) { @@ -29,5 +27,3 @@ void updateCovariancePredicted(BoundMatrix& fullCovariancePredicted, return; } - -} // namespace Acts::Experimental diff --git a/Examples/Algorithms/AmbiguityResolution/src/ScoreBasedAmbiguityResolutionAlgorithm.cpp b/Examples/Algorithms/AmbiguityResolution/src/ScoreBasedAmbiguityResolutionAlgorithm.cpp index f3c7b99219c..41446543dc7 100644 --- a/Examples/Algorithms/AmbiguityResolution/src/ScoreBasedAmbiguityResolutionAlgorithm.cpp +++ b/Examples/Algorithms/AmbiguityResolution/src/ScoreBasedAmbiguityResolutionAlgorithm.cpp @@ -124,9 +124,7 @@ ActsExamples::ScoreBasedAmbiguityResolutionAlgorithm::execute( measurementsPerTracks = m_ambi.computeInitialState( tracks, &sourceLinkHash, &sourceLinkEquality, trackFeaturesVectors); - Acts::ScoreBasedAmbiguityResolution::OptionalCuts< - Acts::ConstVectorTrackContainer, Acts::ConstVectorMultiTrajectory, - std::shared_ptr, true> + Acts::ScoreBasedAmbiguityResolution::OptionalCuts optionalCuts; optionalCuts.cuts.push_back(doubleHolesFilter); std::vector goodTracks = m_ambi.solveAmbiguity( diff --git a/Examples/Algorithms/CMakeLists.txt b/Examples/Algorithms/CMakeLists.txt index bdfc0195b7a..01cc0beaf7f 100644 --- a/Examples/Algorithms/CMakeLists.txt +++ b/Examples/Algorithms/CMakeLists.txt @@ -9,6 +9,7 @@ add_subdirectory(Geometry) add_subdirectory(MaterialMapping) add_subdirectory(Printers) add_subdirectory(Propagation) +add_subdirectory_if(Traccc ACTS_BUILD_PLUGIN_TRACCC) add_subdirectory(TrackFinding) add_subdirectory_if(TrackFindingExaTrkX ACTS_BUILD_EXAMPLES_EXATRKX) add_subdirectory_if(TrackFindingML ACTS_BUILD_PLUGIN_ONNX) diff --git a/Examples/Algorithms/Digitization/include/ActsExamples/Digitization/MeasurementCreation.hpp b/Examples/Algorithms/Digitization/include/ActsExamples/Digitization/MeasurementCreation.hpp index 3d9476815c9..e168858cfd1 100644 --- a/Examples/Algorithms/Digitization/include/ActsExamples/Digitization/MeasurementCreation.hpp +++ b/Examples/Algorithms/Digitization/include/ActsExamples/Digitization/MeasurementCreation.hpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2021 CERN for the benefit of the Acts project +// Copyright (C) 2021-2024 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 @@ -40,9 +40,10 @@ struct DigitizedParameters { /// /// To be used also by the e I/O system /// -/// @return a variant measurement -Measurement createMeasurement(const DigitizedParameters& dParams, - const IndexSourceLink& isl) noexcept(false); +/// @return the measurement proxy +ActsExamples::VariableBoundMeasurementProxy createMeasurement( + MeasurementContainer& container, const DigitizedParameters& dParams, + const IndexSourceLink& isl) noexcept(false); /// Construct the constituents of a measurement. /// diff --git a/Examples/Algorithms/Digitization/src/DigitizationAlgorithm.cpp b/Examples/Algorithms/Digitization/src/DigitizationAlgorithm.cpp index f3b04ac0aff..3ac84f45bac 100644 --- a/Examples/Algorithms/Digitization/src/DigitizationAlgorithm.cpp +++ b/Examples/Algorithms/Digitization/src/DigitizationAlgorithm.cpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2021 CERN for the benefit of the Acts project +// Copyright (C) 2021-2024 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 @@ -268,8 +268,7 @@ ActsExamples::ProcessCode ActsExamples::DigitizationAlgorithm::execute( // be added at the end. sourceLinks.insert(sourceLinks.end(), sourceLink); - measurements.emplace_back( - createMeasurement(dParameters, sourceLink)); + createMeasurement(measurements, dParameters, sourceLink); clusters.emplace_back(std::move(dParameters.cluster)); // this digitization does hit merging so there can be more than one // mapping entry for each digitized hit. diff --git a/Examples/Algorithms/Digitization/src/MeasurementCreation.cpp b/Examples/Algorithms/Digitization/src/MeasurementCreation.cpp index 7338b431f8c..5a9aee23c70 100644 --- a/Examples/Algorithms/Digitization/src/MeasurementCreation.cpp +++ b/Examples/Algorithms/Digitization/src/MeasurementCreation.cpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2021 CERN for the benefit of the Acts project +// Copyright (C) 2021-2024 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 @@ -8,36 +8,35 @@ #include "ActsExamples/Digitization/MeasurementCreation.hpp" +#include "Acts/EventData/MeasurementHelpers.hpp" #include "Acts/EventData/SourceLink.hpp" #include "ActsExamples/EventData/IndexSourceLink.hpp" +#include "ActsExamples/EventData/Measurement.hpp" #include #include #include -ActsExamples::Measurement ActsExamples::createMeasurement( - const DigitizedParameters& dParams, const IndexSourceLink& isl) { +ActsExamples::VariableBoundMeasurementProxy ActsExamples::createMeasurement( + MeasurementContainer& container, const DigitizedParameters& dParams, + const IndexSourceLink& isl) { Acts::SourceLink sl{isl}; - switch (dParams.indices.size()) { - case 1u: { - auto [indices, par, cov] = measurementConstituents<1>(dParams); - return ActsExamples::Measurement(std::move(sl), indices, par, cov); - } - case 2u: { - auto [indices, par, cov] = measurementConstituents<2>(dParams); - return ActsExamples::Measurement(std::move(sl), indices, par, cov); - }; - case 3u: { - auto [indices, par, cov] = measurementConstituents<3>(dParams); - return ActsExamples::Measurement(std::move(sl), indices, par, cov); - }; - case 4u: { - auto [indices, par, cov] = measurementConstituents<4>(dParams); - return ActsExamples::Measurement(std::move(sl), indices, par, cov); - }; - default: - std::string errorMsg = "Invalid/mismatching measurement dimension: " + - std::to_string(dParams.indices.size()); - throw std::runtime_error(errorMsg.c_str()); + + if (dParams.indices.size() > 4u) { + std::string errorMsg = "Invalid/mismatching measurement dimension: " + + std::to_string(dParams.indices.size()); + throw std::runtime_error(errorMsg.c_str()); } + + return Acts::visit_measurement( + dParams.indices.size(), [&](auto dim) -> VariableBoundMeasurementProxy { + auto [indices, par, cov] = measurementConstituents(dParams); + FixedBoundMeasurementProxy measurement = + container.makeMeasurement(); + measurement.setSourceLink(sl); + measurement.setSubspaceIndices(indices); + measurement.parameters() = par; + measurement.covariance() = cov; + return measurement; + }); } diff --git a/Examples/Algorithms/Propagation/include/ActsExamples/Propagation/PropagationAlgorithm.hpp b/Examples/Algorithms/Propagation/include/ActsExamples/Propagation/PropagationAlgorithm.hpp index bbebf9b8625..1cd006d3b45 100644 --- a/Examples/Algorithms/Propagation/include/ActsExamples/Propagation/PropagationAlgorithm.hpp +++ b/Examples/Algorithms/Propagation/include/ActsExamples/Propagation/PropagationAlgorithm.hpp @@ -23,10 +23,6 @@ #include #include -namespace Acts { -class Surface; -} - namespace ActsExamples { class PropagatorInterface; diff --git a/Examples/Algorithms/Traccc/CMakeLists.txt b/Examples/Algorithms/Traccc/CMakeLists.txt new file mode 100644 index 00000000000..11837f12298 --- /dev/null +++ b/Examples/Algorithms/Traccc/CMakeLists.txt @@ -0,0 +1,17 @@ +add_library(ActsExamplesTraccc INTERFACE) + +target_include_directories( + ActsExamplesTraccc + INTERFACE $ +) + +target_link_libraries( + ActsExamplesTraccc + INTERFACE + ActsCore + ActsExamplesFramework + ActsExamplesPropagation + ActsPluginDetray +) + +install(TARGETS ActsExamplesTraccc LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/Examples/Algorithms/Traccc/include/ActsExamples/Traccc/DetrayPropagator.hpp b/Examples/Algorithms/Traccc/include/ActsExamples/Traccc/DetrayPropagator.hpp new file mode 100644 index 00000000000..8c42ecbeab0 --- /dev/null +++ b/Examples/Algorithms/Traccc/include/ActsExamples/Traccc/DetrayPropagator.hpp @@ -0,0 +1,132 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 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 http://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Utilities/Logger.hpp" +#include "Acts/Utilities/Result.hpp" +#include "ActsExamples/EventData/PropagationSummary.hpp" +#include "ActsExamples/Propagation/PropagationAlgorithm.hpp" +#include "ActsExamples/Propagation/PropagatorInterface.hpp" +#include "ActsExamples/Traccc/DetrayStore.hpp" + +#include +#include + +namespace ActsExamples { + +/// Define the algebra type +using DetrayAlgebraType = typename Acts::DetrayHostDetector::algebra_type; + +/// Type that holds the intersection information +using DetrayIntersection = + detray::intersection2D; + +/// Inspector that records all encountered surfaces +using DetrayObjectTracer = + detray::navigation::object_tracer; + +/// Inspector that prints the navigator state from within the navigator's +/// method calls (cannot be done with an actor) +using DetrayPrintInspector = detray::navigation::print_inspector; + +template +class DetrayPropagator : public PropagatorInterface { + public: + /// Create a DetrayPropagator + /// + /// @param propagator The actual detray propagator to wrap + /// @param detrayStore The detray store to access the detector + /// @param logger The logger instance + DetrayPropagator(propagator_t&& propagator, + std::shared_ptr detrayStore, + std::unique_ptr logger = + Acts::getDefaultLogger("DetrayPropagator", + Acts::Logging::INFO)) + : PropagatorInterface(), + m_propagator(std::move(propagator)), + m_detrayStore(std::move(detrayStore)), + m_logger(std::move(logger)) {} + + ///@brief Execute a propagation for charged particle parameters + /// + ///@param context The algorithm context + ///@param cfg The propagation algorithm configuration + ///@param logger A logger wrapper instance + ///@param startParameters The start parameters + ///@return PropagationOutput + Acts::Result execute( + const AlgorithmContext& context, + [[maybe_unused]] const PropagationAlgorithm::Config& cfg, + const Acts::Logger& logger, + const Acts::BoundTrackParameters& startParameters) const final { + // Get the geometry context form the algorithm context + const auto& geoContext = context.geoContext; + // Get the track information + const Acts::Vector3 position = startParameters.position(geoContext); + const Acts::Vector3 direction = startParameters.momentum().normalized(); + + ACTS_VERBOSE("Starting propagation at " << position.transpose() + << " with direction " + << direction.transpose()); + + // Now follow that ray with the same track and check, if we find + // the same volumes and distances along the way + detray::free_track_parameters track( + {position.x(), position.y(), position.z()}, 0.f, + {direction.x(), direction.y(), direction.z()}, + startParameters.charge()); + + typename propagator_t::state propagation(track, m_detrayStore->detector); + + // Run the actual propagation + m_propagator.propagate(propagation); + + // Retrieve navigation information + auto& inspector = propagation._navigation.inspector(); + auto& objectTracer = inspector.template get(); + + PropagationSummary summary(startParameters); + // Translate the objects into the steps + for (const auto& object : objectTracer.object_trace) { + // Get the position of the object + const auto& dposition = object.pos; + const auto& sfDesription = object.intersection.sf_desc; + const auto sf = + detray::tracking_surface{m_detrayStore->detector, sfDesription}; + Acts::GeometryIdentifier geoID{sf.source()}; + // Create a step from the object + Acts::detail::Step step; + step.position = Acts::Vector3(dposition[0], dposition[1], dposition[2]); + step.geoID = geoID; + step.navDir = object.intersection.direction ? Acts::Direction::Forward + : Acts::Direction::Backward; + summary.steps.emplace_back(step); + } + RecordedMaterial recordedMaterial; + return std::pair{std::move(summary), std::move(recordedMaterial)}; + } + + private: + /// The propagator @todo fix when propagate() method is const in detray + mutable propagator_t m_propagator; + + /// The detray detector store and memory resource + std::shared_ptr m_detrayStore = nullptr; + + /// The logging instance + std::unique_ptr m_logger = nullptr; + + const Acts::Logger& logger() const { return *m_logger; } +}; + +} // namespace ActsExamples diff --git a/Examples/Algorithms/Traccc/include/ActsExamples/Traccc/DetrayStore.hpp b/Examples/Algorithms/Traccc/include/ActsExamples/Traccc/DetrayStore.hpp new file mode 100644 index 00000000000..c2ccb9f6119 --- /dev/null +++ b/Examples/Algorithms/Traccc/include/ActsExamples/Traccc/DetrayStore.hpp @@ -0,0 +1,55 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 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 http://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Plugins/Detray/DetrayConversionUtils.hpp" +#include "Acts/Plugins/Detray/DetrayConverter.hpp" + +#include + +#include +#include + +namespace ActsExamples { + +// The Detray host store that is used to store the detector +// and the associated memory resource +template +struct DetrayStore { + // Constructor from arguments + DetrayStore(std::shared_ptr mSource, + Acts::DetrayHostDetector&& det) + : memoryResource(std::move(mSource)), detector(std::move(det)) {} + + // The memory resource + std::shared_ptr memoryResource = nullptr; + // The detray detector instance + Acts::DetrayHostDetector detector; + + // Create a Detray detector and store it with its memory Source in + /// + /// @param gctx the geometry context + /// @param detector the detector to be converted + /// @param options the conversion options + static inline std::shared_ptr> create( + const Acts::GeometryContext& gctx, + const Acts::Experimental::Detector& detector, + const Acts::DetrayConverter::Options& options) { + auto memoryResource = std::make_shared(); + auto DetrayHostDetector = Acts::DetrayConverter().convert<>( + gctx, detector, *memoryResource, options); + + return std::make_shared>( + memoryResource, std::move(DetrayHostDetector)); + } +}; + +using DetrayHostStore = DetrayStore; + +} // namespace ActsExamples diff --git a/Examples/Algorithms/TrackFinding/src/HoughTransformSeeder.cpp b/Examples/Algorithms/TrackFinding/src/HoughTransformSeeder.cpp index 25d9d7f2e25..3c16d146d65 100644 --- a/Examples/Algorithms/TrackFinding/src/HoughTransformSeeder.cpp +++ b/Examples/Algorithms/TrackFinding/src/HoughTransformSeeder.cpp @@ -529,7 +529,8 @@ void ActsExamples::HoughTransformSeeder::addMeasurements( // are transformed to the bound space where we do know their location. // if the local parameters are not measured, this results in a // zero location, which is a reasonable default fall-back. - const auto& measurement = measurements[sourceLink.index()]; + const ConstVariableBoundMeasurementProxy measurement = + measurements.getMeasurement(sourceLink.index()); assert(measurement.contains(Acts::eBoundLoc0) && "Measurement does not contain the required bound loc0"); diff --git a/Examples/Algorithms/TrackFinding/src/SpacePointMaker.cpp b/Examples/Algorithms/TrackFinding/src/SpacePointMaker.cpp index 49802b57087..0605e1b4bc4 100644 --- a/Examples/Algorithms/TrackFinding/src/SpacePointMaker.cpp +++ b/Examples/Algorithms/TrackFinding/src/SpacePointMaker.cpp @@ -126,7 +126,8 @@ ActsExamples::ProcessCode ActsExamples::SpacePointMaker::execute( spOpt.paramCovAccessor = [&measurements](Acts::SourceLink slink) { const auto islink = slink.get(); - const auto& meas = measurements[islink.index()]; + const ConstVariableBoundMeasurementProxy meas = + measurements.getMeasurement(islink.index()); return std::make_pair(meas.fullParameters(), meas.fullCovariance()); }; diff --git a/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithm.cpp b/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithm.cpp index 5799851fe9a..bb88f0e0208 100644 --- a/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithm.cpp +++ b/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithm.cpp @@ -421,6 +421,8 @@ ProcessCode TrackFindingAlgorithm::execute(const AlgorithmContext& ctx) const { } }); + Acts::calculateTrackQuantities(track); + if (m_trackSelector.has_value() && !m_trackSelector->isValidTrack(track)) { return; } @@ -505,6 +507,10 @@ ProcessCode TrackFindingAlgorithm::execute(const AlgorithmContext& ctx) const { // has already been updated seedNumber(trackCandidate) = nSeed - 1; + auto firstState = *std::next(trackCandidate.trackStatesReversed().begin(), + trackCandidate.nTrackStates() - 1); + assert(firstState.previous() == Acts::kTrackIndexInvalid); + if (m_cfg.twoWay) { std::optional firstMeasurement; @@ -532,18 +538,8 @@ ProcessCode TrackFindingAlgorithm::execute(const AlgorithmContext& ctx) const { ACTS_WARNING("Second track finding failed for seed " << iSeed << " with error" << secondResult.error()); } else { - auto firstState = - *std::next(trackCandidate.trackStatesReversed().begin(), - trackCandidate.nTrackStates() - 1); - assert(firstState.previous() == Acts::kTrackIndexInvalid); - auto& secondTracksForSeed = secondResult.value(); for (auto& secondTrack : secondTracksForSeed) { - if (!secondTrack.hasReferenceSurface()) { - ACTS_WARNING("Second track has no reference surface."); - continue; - } - // TODO a copy of the track should not be necessary but is the // safest way with the current EDM // TODO a lightweight copy without copying all the track state @@ -559,17 +555,19 @@ ProcessCode TrackFindingAlgorithm::execute(const AlgorithmContext& ctx) const { firstState.previous() = secondTrackCopy.outermostTrackState().index(); + trackCandidate.copyFrom(secondTrackCopy, false); + // finalize the track candidate + bool doExtrapolate = true; + if (!m_cfg.reverseSearch) { // these parameters are already extrapolated by the CKF and have // the optimal resolution. note that we did not smooth all the // states. - trackCandidate.parameters() = secondTrackCopy.parameters(); - trackCandidate.covariance() = secondTrackCopy.covariance(); - trackCandidate.setReferenceSurface( - secondTrackCopy.referenceSurface().getSharedPtr()); + // only extrapolate if we did not do it already + doExtrapolate = !trackCandidate.hasReferenceSurface(); } else { // smooth the full track and extrapolate to the reference @@ -585,7 +583,9 @@ ProcessCode TrackFindingAlgorithm::execute(const AlgorithmContext& ctx) const { } trackCandidate.reverseTrackStates(true); + } + if (doExtrapolate) { auto secondExtrapolationResult = Acts::extrapolateTrackToReferenceSurface( trackCandidate, *pSurface, extrapolator, @@ -601,23 +601,20 @@ ProcessCode TrackFindingAlgorithm::execute(const AlgorithmContext& ctx) const { } } - Acts::calculateTrackQuantities(trackCandidate); - addTrack(trackCandidate); ++nSecond; } - - // restore `trackCandidate` to its original state in case we need it - // again - firstState.previous() = Acts::kTrackIndexInvalid; - Acts::calculateTrackQuantities(trackCandidate); } } } // if no second track was found, we will use only the first track if (nSecond == 0) { + // restore the track to the original state + trackCandidate.copyFrom(firstTrack, false); + firstState.previous() = Acts::kTrackIndexInvalid; + auto firstExtrapolationResult = Acts::extrapolateTrackToReferenceSurface( trackCandidate, *pSurface, extrapolator, extrapolationOptions, diff --git a/Examples/Algorithms/TrackFindingML/include/ActsExamples/TrackFindingML/AmbiguityDBScanClustering.hpp b/Examples/Algorithms/TrackFindingML/include/ActsExamples/TrackFindingML/AmbiguityDBScanClustering.hpp index 16a5801f971..efe7ef0aa5f 100644 --- a/Examples/Algorithms/TrackFindingML/include/ActsExamples/TrackFindingML/AmbiguityDBScanClustering.hpp +++ b/Examples/Algorithms/TrackFindingML/include/ActsExamples/TrackFindingML/AmbiguityDBScanClustering.hpp @@ -9,6 +9,7 @@ #pragma once #include "Acts/EventData/TrackContainer.hpp" +#include "Acts/EventData/TrackContainerFrontendConcept.hpp" #include "Acts/TrackFinding/detail/AmbiguityTrackClustering.hpp" #include "Acts/Utilities/DBScan.hpp" @@ -25,13 +26,11 @@ namespace Acts { /// @param epsilon Maximum distance between 2 tracks to be clustered /// @param minPoints Minimum number of tracks to create a cluster /// @return an unordered map representing the clusters, the keys the ID of the primary track of each cluster and the store a vector of track IDs. -template class holder_t> +template std::unordered_map> dbscanTrackClustering( std::multimap>>& trackMap, - const Acts::TrackContainer& tracks, - float epsilon = 0.07, int minPoints = 2) { + const track_container_t& tracks, float epsilon = 0.07, int minPoints = 2) { // Unordered map associating a vector with all the track ID of a cluster to // the ID of the first track of the cluster std::unordered_map> cluster; diff --git a/Examples/Algorithms/TrackFitting/src/TrackFittingAlgorithm.cpp b/Examples/Algorithms/TrackFitting/src/TrackFittingAlgorithm.cpp index f80f20570c5..0a352d71fe6 100644 --- a/Examples/Algorithms/TrackFitting/src/TrackFittingAlgorithm.cpp +++ b/Examples/Algorithms/TrackFitting/src/TrackFittingAlgorithm.cpp @@ -18,6 +18,7 @@ #include "Acts/Surfaces/PerigeeSurface.hpp" #include "Acts/Surfaces/Surface.hpp" #include "Acts/Utilities/Result.hpp" +#include "ActsExamples/EventData/Measurement.hpp" #include "ActsExamples/EventData/MeasurementCalibration.hpp" #include "ActsExamples/EventData/ProtoTrack.hpp" #include "ActsExamples/Framework/AlgorithmContext.hpp" @@ -126,7 +127,8 @@ ActsExamples::ProcessCode ActsExamples::TrackFittingAlgorithm::execute( // Fill the source links via their indices from the container for (auto hitIndex : protoTrack) { - const auto& measurement = measurements.at(hitIndex); + ConstVariableBoundMeasurementProxy measurement = + measurements.getMeasurement(hitIndex); trackSourceLinks.push_back(measurement.sourceLink()); } diff --git a/Examples/Framework/CMakeLists.txt b/Examples/Framework/CMakeLists.txt index bfe33f2e8e6..692db8f2f15 100644 --- a/Examples/Framework/CMakeLists.txt +++ b/Examples/Framework/CMakeLists.txt @@ -5,6 +5,7 @@ set(ActsExamplesFramework_SOURCES) add_library( ActsExamplesFramework SHARED + src/EventData/Measurement.cpp src/EventData/MeasurementCalibration.cpp src/EventData/ScalingCalibrator.cpp src/Framework/IAlgorithm.cpp diff --git a/Examples/Framework/ML/src/NeuralCalibrator.cpp b/Examples/Framework/ML/src/NeuralCalibrator.cpp index 77af3920a6a..54003b3bfc1 100644 --- a/Examples/Framework/ML/src/NeuralCalibrator.cpp +++ b/Examples/Framework/ML/src/NeuralCalibrator.cpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2023 CERN for the benefit of the Acts project +// Copyright (C) 2023-2024 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 @@ -106,7 +106,8 @@ void ActsExamples::NeuralCalibrator::calibrate( const Acts::Surface& referenceSurface = trackState.referenceSurface(); auto trackParameters = trackState.parameters(); - const auto& measurement = measurements[idxSourceLink.index()]; + const ConstVariableBoundMeasurementProxy measurement = + measurements.getMeasurement(idxSourceLink.index()); assert(measurement.contains(Acts::eBoundLoc0) && "Measurement does not contain the required bound loc0"); @@ -171,21 +172,24 @@ void ActsExamples::NeuralCalibrator::calibrate( std::size_t iLoc0 = m_nComponents + iMax * 2; std::size_t iVar0 = 3 * m_nComponents + iMax * 2; - Measurement measurementCopy = measurement; - measurementCopy.parameters()[boundLoc0] = output[iLoc0]; - measurementCopy.parameters()[boundLoc1] = output[iLoc0 + 1]; - measurementCopy.covariance()(boundLoc0, boundLoc0) = output[iVar0]; - measurementCopy.covariance()(boundLoc1, boundLoc1) = output[iVar0 + 1]; - Acts::visit_measurement(measurement.size(), [&](auto N) -> void { constexpr std::size_t kMeasurementSize = decltype(N)::value; + const ConstFixedBoundMeasurementProxy fixedMeasurement = + measurement; + + Acts::ActsVector calibratedParameters = + fixedMeasurement.parameters(); + Acts::ActsSquareMatrix calibratedCovariance = + fixedMeasurement.covariance(); + + calibratedParameters[boundLoc0] = output[iLoc0]; + calibratedParameters[boundLoc1] = output[iLoc0 + 1]; + calibratedCovariance(boundLoc0, boundLoc0) = output[iVar0]; + calibratedCovariance(boundLoc1, boundLoc1) = output[iVar0 + 1]; trackState.allocateCalibrated(kMeasurementSize); - trackState.calibrated() = - measurementCopy.parameters(); - trackState.calibratedCovariance() = - measurementCopy.covariance(); - trackState.setSubspaceIndices( - measurementCopy.subspaceIndices()); + trackState.calibrated() = calibratedParameters; + trackState.calibratedCovariance() = calibratedCovariance; + trackState.setSubspaceIndices(fixedMeasurement.subspaceIndices()); }); } diff --git a/Examples/Framework/include/ActsExamples/EventData/Measurement.hpp b/Examples/Framework/include/ActsExamples/EventData/Measurement.hpp index 87c4c546c08..31193f6818d 100644 --- a/Examples/Framework/include/ActsExamples/EventData/Measurement.hpp +++ b/Examples/Framework/include/ActsExamples/EventData/Measurement.hpp @@ -8,6 +8,7 @@ #pragma once +#include "Acts/Definitions/Algebra.hpp" #include "Acts/Definitions/TrackParametrization.hpp" #include "Acts/EventData/MeasurementHelpers.hpp" #include "Acts/EventData/SourceLink.hpp" @@ -28,253 +29,460 @@ namespace ActsExamples { -/// A measurement of a variable-size subspace of the full parameters. +template +class MeasurementProxyBase; +template +class FixedMeasurementProxy; +template +class VariableMeasurementProxy; + +template +using FixedBoundMeasurementProxy = + FixedMeasurementProxy; +template +using ConstFixedBoundMeasurementProxy = + FixedMeasurementProxy; +using VariableBoundMeasurementProxy = + VariableMeasurementProxy; +using ConstVariableBoundMeasurementProxy = + VariableMeasurementProxy; + +/// @brief A container to store and access measurements /// -/// @tparam indices_t Parameter index type, determines the full parameter space +/// This container stores measurements of different sizes and provides +/// access to them through fixed-size and variable-size proxies. /// -/// The measurement intentionally does not store a pointer/reference to the -/// reference object in the geometry hierarchy, i.e. the surface or volume. The -/// reference object can already be identified via the geometry identifier -/// provided by the source link. Since a measurement **must** be anchored within -/// the geometry hierarchy, all measurement surfaces and volumes **must** -/// provide valid geometry identifiers. In all use-cases, e.g. Kalman filtering, -/// a pointer/reference to the reference object is available before the -/// measurement is accessed; e.g. the propagator provides the surface pointer -/// during navigation, which is then used to lookup possible measurements. -/// -/// The pointed-to geometry object would differ depending on the parameter type. -/// This means either, that there needs to be an additional variable type or -/// that a pointer to a base object is stored (requiring a `dynamic_cast` later -/// on). Both variants add additional complications. Since the geometry object -/// is not required anyway (as discussed above), not storing it removes all -/// these complications altogether. -template -class VariableSizeMeasurement { +/// The measurements are stored densely in a flat buffer and the proxies +/// provide access to the individual measurements. +class MeasurementContainer { public: - static constexpr std::size_t kFullSize = - Acts::detail::kParametersSize; - - using Scalar = Acts::ActsScalar; + using Index = std::size_t; + template + using FixedProxy = FixedMeasurementProxy; + template + using ConstFixedProxy = FixedMeasurementProxy; + using VariableProxy = VariableMeasurementProxy; + using ConstVariableProxy = VariableMeasurementProxy; + + MeasurementContainer(); + + /// @brief Get the number of measurements + /// @return The number of measurements + std::size_t size() const; + + /// @brief Reserve space for a number of measurements + /// @param size The number of measurements to reserve space for + void reserve(std::size_t size); + + /// @brief Add a measurement of a given size + /// @param size The size of the measurement + /// @return The index of the added measurement + Index addMeasurement(std::uint8_t size); + + /// @brief Get a variable-size measurement proxy + /// @param index The index of the measurement + /// @return The variable-size measurement proxy + VariableProxy getMeasurement(Index index); + /// @brief Get a const variable-size measurement proxy + /// @param index The index of the measurement + /// @return The const variable-size measurement proxy + ConstVariableProxy getMeasurement(Index index) const; + + /// @brief Get a fixed-size measurement proxy + /// @tparam Size The size of the measurement + /// @param index The index of the measurement + /// @return The fixed-size measurement proxy + template + FixedProxy getMeasurement(Index index) { + return FixedProxy{*this, index}; + } + /// @brief Get a const fixed-size measurement proxy + /// @tparam Size The size of the measurement + /// @param index The index of the measurement + /// @return The const fixed-size measurement proxy + template + ConstFixedProxy getMeasurement(Index index) const { + return ConstFixedProxy{*this, index}; + } - using SubspaceIndex = std::uint8_t; - using SubspaceIndices = - boost::container::static_vector; - - /// Vector type containing for measured parameter values. - template - using ParametersVector = Eigen::Matrix; - template - using ParametersVectorMap = Eigen::Map>; - template - using ConstParametersVectorMap = Eigen::Map>; - using EffectiveParametersVector = Eigen::Matrix; - using EffectiveParametersVectorMap = Eigen::Map; - using ConstEffectiveParametersVectorMap = - Eigen::Map; - - /// Matrix type for the measurement covariance. - template - using CovarianceMatrix = Eigen::Matrix; - template - using CovarianceMatrixMap = Eigen::Map>; - template - using ConstCovarianceMatrixMap = Eigen::Map>; - using EffectiveCovarianceMatrix = - Eigen::Matrix; - using EffectiveCovarianceMatrixMap = Eigen::Map; - using ConstEffectiveCovarianceMatrixMap = - Eigen::Map; - - using FullParametersVector = Acts::ActsVector; - using FullCovarianceMatrix = Acts::ActsSquareMatrix; - - using ProjectionMatrix = Eigen::Matrix; - using ExpansionMatrix = Eigen::Matrix; - - /// Construct from source link, subset indices, and measured data. - /// - /// @tparam parameters_t Input parameters vector type - /// @tparam covariance_t Input covariance matrix type - /// @param source The link that connects to the underlying detector readout - /// @param subspaceIndices Which parameters are measured - /// @param params Measured parameters values - /// @param cov Measured parameters covariance - /// - /// @note The indices must be ordered and must describe/match the content - /// of parameters and covariance. - template - VariableSizeMeasurement( - Acts::SourceLink source, - const std::array& subspaceIndices, - const Eigen::MatrixBase& params, - const Eigen::MatrixBase& cov) - : m_source(std::move(source)) { - static_assert(kSize == parameters_t::RowsAtCompileTime, - "Parameter size mismatch"); - static_assert(kSize == covariance_t::RowsAtCompileTime, - "Covariance rows mismatch"); - static_assert(kSize == covariance_t::ColsAtCompileTime, - "Covariance cols mismatch"); - - m_subspaceIndices.resize(subspaceIndices.size()); - std::transform(subspaceIndices.begin(), subspaceIndices.end(), - m_subspaceIndices.begin(), [](auto index) { - return static_cast(index); - }); - - parameters() = params; - covariance() = cov; + /// @brief Make a measurement of a given size + /// @param size The size of the measurement + /// @return The variable-size measurement proxy + VariableProxy makeMeasurement(std::uint8_t size); + /// @brief Make a fixed-size measurement + /// @tparam Size The size of the measurement + /// @return The fixed-size measurement proxy + template + FixedProxy makeMeasurement() { + return getMeasurement(addMeasurement(Size)); } - /// A measurement can only be constructed with valid parameters. - VariableSizeMeasurement() = delete; - VariableSizeMeasurement(const VariableSizeMeasurement&) = default; - VariableSizeMeasurement(VariableSizeMeasurement&&) = default; - ~VariableSizeMeasurement() = default; - VariableSizeMeasurement& operator=(const VariableSizeMeasurement&) = default; - VariableSizeMeasurement& operator=(VariableSizeMeasurement&&) = default; - /// Source link that connects to the underlying detector readout. - const Acts::SourceLink& sourceLink() const { return m_source; } + template + class IteratorImpl { + public: + using value_type = + std::conditional_t; + using reference = value_type; + using pointer = value_type*; + using difference_type = std::ptrdiff_t; + using iterator_category = std::forward_iterator_tag; + + using Container = std::conditional_t; + + IteratorImpl(Container& container, std::size_t index) + : m_container(container), m_index(index) {} - constexpr std::size_t size() const { return m_subspaceIndices.size(); } + reference operator*() const { return m_container.getMeasurement(m_index); } + + pointer operator->() const { return &operator*(); } + + IteratorImpl& operator++() { + ++m_index; + return *this; + } + + IteratorImpl operator++(int) { + auto copy = *this; + ++*this; + return copy; + } + + bool operator==(const IteratorImpl& other) const { + return m_index == other.m_index; + } - /// Check if a specific parameter is part of this measurement. + bool operator!=(const IteratorImpl& other) const { + return !(*this == other); + } + + private: + Container& m_container; + Index m_index; + }; + + using iterator = IteratorImpl; + using const_iterator = IteratorImpl; + + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + const_iterator cbegin() const; + const_iterator cend() const; + + public: + struct MeasurementEntry { + std::size_t subspaceIndexOffset{}; + std::size_t parameterOffset{}; + std::size_t covarianceOffset{}; + std::uint8_t size{}; + }; + + std::vector m_entries; + + std::vector> m_sourceLinks; + std::vector m_subspaceIndices; + std::vector m_parameters; + std::vector m_covariances; +}; + +/// @brief Base class for measurement proxies +/// +/// This class provides common functionality for fixed-size and variable-size +/// measurement proxies. +/// +/// @tparam Derived The derived measurement proxy class +/// @tparam FullSize The full size of the measurement +/// @tparam ReadOnly Whether the proxy is read-only +template +class MeasurementProxyBase { + public: + using Index = MeasurementContainer::Index; + using SubspaceIndex = std::uint8_t; + using Scalar = double; + + using FullVector = Acts::ActsVector; + using FullSquareMatrix = Acts::ActsSquareMatrix; + + using Container = std::conditional_t; + + MeasurementProxyBase(Container& container_, Index index_) + : m_container(&container_), m_index(index_) {} + template + MeasurementProxyBase( + const MeasurementProxyBase& other) + requires(ReadOnly == OtherReadOnly || ReadOnly) + : m_container(&other.container()), m_index(other.index()) {} + + /// @brief Get the container of the measurement + /// @return The container of the measurement + Container& container() const { return *m_container; } + /// @brief Get the index of the measurement + /// @return The index of the measurement + Index index() const { return m_index; } + + /// @brief Get the size of the measurement + /// @return The size of the measurement + std::size_t size() const { return container().m_entries.at(m_index).size; } + + /// @brief Check if the measurement contains a subspace index + /// @param i The subspace index + /// @return True if the measurement contains the subspace index + template bool contains(indices_t i) const { - return std::find(m_subspaceIndices.begin(), m_subspaceIndices.end(), i) != - m_subspaceIndices.end(); + return self().subspaceHelper().contains(i); } + /// @brief Get the index of a subspace index in the measurement + /// @param i The subspace index + /// @return The index of the subspace index in the measurement + template std::size_t indexOf(indices_t i) const { - auto it = std::find(m_subspaceIndices.begin(), m_subspaceIndices.end(), i); - assert(it != m_subspaceIndices.end()); - return std::distance(m_subspaceIndices.begin(), it); + return self().subspaceHelper().indexOf(i); } - /// The measurement indices - const SubspaceIndices& subspaceIndices() const { return m_subspaceIndices; } + /// @brief Set the source link of the measurement + /// @param sourceLink The source link + void setSourceLink(const Acts::SourceLink& sourceLink) + requires(!ReadOnly) + { + container().m_sourceLinks.at(m_index) = sourceLink; + } - template - Acts::SubspaceIndices subspaceIndices() const { - assert(dim == size()); - Acts::SubspaceIndices result; - std::copy(m_subspaceIndices.begin(), m_subspaceIndices.end(), - result.begin()); - return result; + /// @brief Get the source link of the measurement + /// @return The source link + const Acts::SourceLink& sourceLink() const { + return container().m_sourceLinks.at(m_index).value(); } - Acts::BoundSubspaceIndices boundSubsetIndices() const - requires(std::is_same_v) + /// @brief Set the subspace indices of the measurement + /// @param indices The subspace indices + template + void setSubspaceIndices(const IndexContainer& indices) + requires(!ReadOnly) { - Acts::BoundSubspaceIndices result = Acts::kBoundSubspaceIndicesInvalid; - std::copy(m_subspaceIndices.begin(), m_subspaceIndices.end(), - result.begin()); - return result; + assert(checkSubspaceIndices(indices, FullSize, size()) && + "Invalid indices"); + std::transform(indices.begin(), indices.end(), + self().subspaceIndexVector().begin(), + [](auto index) { return static_cast(index); }); } - template - ConstParametersVectorMap parameters() const { - assert(dim == size()); - return ConstParametersVectorMap{m_params.data()}; + /// @brief Get the measurement as a full-size vector + /// @return The full-size measurement vector + FullVector fullParameters() const { + return self().subspaceHelper().expandVector(self().parameters()); } - template - ParametersVectorMap parameters() { - assert(dim == size()); - return ParametersVectorMap{m_params.data()}; - } - ConstEffectiveParametersVectorMap parameters() const { - return ConstEffectiveParametersVectorMap{m_params.data(), - static_cast(size())}; + + /// @brief Get the covariance as a full-size square matrix + /// @return The full-size covariance matrix + FullSquareMatrix fullCovariance() const { + return self().subspaceHelper().expandMatrix(self().covariance()); } - EffectiveParametersVectorMap parameters() { - return EffectiveParametersVectorMap{m_params.data(), - static_cast(size())}; + + /// @brief Copy the data from another measurement + /// @tparam OtherDerived The derived measurement proxy class of the other + /// measurement + /// @param other The other measurement proxy + template + void copyFrom(const OtherDerived& other) + requires(!ReadOnly) + { + assert(size() == other.size() && "Size mismatch"); + setSourceLink(other.sourceLink()); + self().subspaceIndexVector() = other.subspaceIndexVector(); + self().parameters() = other.parameters(); + self().covariance() = other.covariance(); } - template - ConstCovarianceMatrixMap covariance() const { - assert(dim == size()); - return ConstCovarianceMatrixMap{m_cov.data()}; + protected: + Derived& self() { return static_cast(*this); } + const Derived& self() const { return static_cast(*this); } + + Container* m_container; + Index m_index; +}; + +/// @brief Fixed-size measurement proxy +/// +/// This class provides access to a fixed-size measurement in a measurement +/// container. +/// +/// @tparam FullSize The full size of the measurement +/// @tparam Size The size of the measurement +/// @tparam ReadOnly Whether the proxy is read-only +template +class FixedMeasurementProxy + : public MeasurementProxyBase< + FixedMeasurementProxy, FullSize, ReadOnly> { + public: + using Base = + MeasurementProxyBase, + FullSize, ReadOnly>; + using Index = typename Base::Index; + using SubspaceIndex = typename Base::SubspaceIndex; + using Scalar = typename Base::Scalar; + using Container = typename Base::Container; + + using SubspaceHelper = Acts::FixedSubspaceHelper; + + using SubspaceVector = Eigen::Matrix; + using SubspaceVectorMap = + std::conditional_t, + Eigen::Map>; + + using ParametersVector = Eigen::Matrix; + using ParametersVectorMap = + std::conditional_t, + Eigen::Map>; + + using CovarianceMatrix = Eigen::Matrix; + using CovarianceMatrixMap = + std::conditional_t, + Eigen::Map>; + + FixedMeasurementProxy(Container& container_, Index index_) + : Base(container_, index_) { + assert(container().m_entries.at(index()).size == Size && "Size mismatch"); } - template - CovarianceMatrixMap covariance() { - assert(dim == size()); - return CovarianceMatrixMap{m_cov.data()}; + template + FixedMeasurementProxy( + const MeasurementProxyBase& other) + requires(ReadOnly == OtherReadOnly || ReadOnly) + : Base(other) { + assert(container().m_entries.at(index()).size == Size && "Size mismatch"); } - ConstEffectiveCovarianceMatrixMap covariance() const { - return ConstEffectiveCovarianceMatrixMap{m_cov.data(), - static_cast(size()), - static_cast(size())}; + + using Base::container; + using Base::index; + + /// @brief Get the size of the measurement + /// @return The size of the measurement + static constexpr std::size_t size() { return Size; } + + /// @brief Get the subspace helper for the measurement + /// @return The subspace helper + SubspaceHelper subspaceHelper() const { + return SubspaceHelper{subspaceIndexVector()}; } - EffectiveCovarianceMatrixMap covariance() { - return EffectiveCovarianceMatrixMap{m_cov.data(), - static_cast(size()), - static_cast(size())}; + + /// @brief Get the subspace indices of the measurement + /// @return The subspace indices + Acts::SubspaceIndices subspaceIndices() const { + return subspaceHelper().indices(); } - FullParametersVector fullParameters() const { - FullParametersVector result = FullParametersVector::Zero(); - for (std::size_t i = 0; i < size(); ++i) { - result[m_subspaceIndices[i]] = parameters()[i]; - } - return result; + /// @brief Get the subspace index vector of the measurement + /// @return The subspace index vector + SubspaceVectorMap subspaceIndexVector() const { + return SubspaceVectorMap{ + container().m_subspaceIndices.data() + + container().m_entries.at(index()).subspaceIndexOffset}; } - FullCovarianceMatrix fullCovariance() const { - FullCovarianceMatrix result = FullCovarianceMatrix::Zero(); - for (std::size_t i = 0; i < size(); ++i) { - for (std::size_t j = 0; j < size(); ++j) { - result(m_subspaceIndices[i], m_subspaceIndices[j]) = covariance()(i, j); - } - } - return result; + /// @brief Get the parameters of the measurement + /// @return The parameters + ParametersVectorMap parameters() const { + return ParametersVectorMap{ + container().m_parameters.data() + + container().m_entries.at(index()).parameterOffset}; } - private: - Acts::SourceLink m_source; - SubspaceIndices m_subspaceIndices; - std::array m_params{}; - std::array m_cov{}; + /// @brief Get the covariance of the measurement + /// @return The covariance + CovarianceMatrixMap covariance() const { + return CovarianceMatrixMap{ + container().m_covariances.data() + + container().m_entries.at(index()).covarianceOffset}; + } }; -/// Construct a variable-size measurement for the given indices. -/// -/// @tparam parameters_t Input parameters vector type -/// @tparam covariance_t Input covariance matrix type -/// @tparam indices_t Parameter index type, determines the full parameter space -/// @tparam tail_indices_t Helper types required to support variadic arguments; -/// all types must be convertibale to `indices_t`. -/// @param source The link that connects to the underlying detector readout -/// @param params Measured parameters values -/// @param cov Measured parameters covariance -/// @param index0 Required parameter index, measurement must be at least 1d -/// @param tailIndices Additional parameter indices for larger measurements -/// @return Variable-size measurement w/ the correct type and given inputs +/// @brief Variable-size measurement proxy /// -/// @note The indices must be ordered and must be consistent with the content of -/// parameters and covariance. -template -VariableSizeMeasurement makeVariableSizeMeasurement( - Acts::SourceLink source, const Eigen::MatrixBase& params, - const Eigen::MatrixBase& cov, indices_t index0, - tail_indices_t... tailIndices) { - using IndexContainer = std::array; - return {std::move(source), IndexContainer{index0, tailIndices...}, params, - cov}; -} - -/// Type that can hold all possible bound measurements. -using BoundVariableMeasurement = VariableSizeMeasurement; - -/// Variable measurement type that can contain all possible combinations. -using Measurement = BoundVariableMeasurement; - -/// Container of measurements. +/// This class provides access to a variable-size measurement in a measurement +/// container. /// -/// In contrast to the source links, the measurements themself must not be -/// orderable. The source links stored in the measurements are treated -/// as opaque here and no ordering is enforced on the stored measurements. -using MeasurementContainer = std::vector; +/// @tparam FullSize The full size of the measurement +/// @tparam ReadOnly Whether the proxy is read-only +template +class VariableMeasurementProxy + : public MeasurementProxyBase, + FullSize, ReadOnly> { + public: + using Base = + MeasurementProxyBase, + FullSize, ReadOnly>; + using Index = typename Base::Index; + using SubspaceIndex = typename Base::SubspaceIndex; + using Scalar = typename Base::Scalar; + using Container = typename Base::Container; + + using SubspaceHelper = Acts::VariableSubspaceHelper; + + using SubspaceVector = Eigen::Matrix; + using SubspaceVectorMap = + std::conditional_t, + Eigen::Map>; + + using ParametersVector = Eigen::Matrix; + using ParametersVectorMap = + std::conditional_t, + Eigen::Map>; + + using CovarianceMatrix = + Eigen::Matrix; + using CovarianceMatrixMap = + std::conditional_t, + Eigen::Map>; + + VariableMeasurementProxy(Container& container_, Index index_) + : Base(container_, index_) {} + template + VariableMeasurementProxy( + const MeasurementProxyBase& other) + requires(ReadOnly == OtherReadOnly || ReadOnly) + : Base(other) {} + + using Base::container; + using Base::index; + + /// @brief Get the subspace helper for the measurement + /// @return The subspace helper + SubspaceHelper subspaceHelper() const { + return SubspaceHelper{subspaceIndexVector()}; + } + + /// @brief Get the subspace indices of the measurement + /// @return The subspace indices + SubspaceVectorMap subspaceIndexVector() const { + const auto size = static_cast(this->size()); + return SubspaceVectorMap{ + container().m_subspaceIndices.data() + + container().m_entries.at(index()).subspaceIndexOffset, + size}; + } + + /// @brief Get the parameters of the measurement + /// @return The parameters + ParametersVectorMap parameters() const { + const auto size = static_cast(this->size()); + return ParametersVectorMap{ + container().m_parameters.data() + + container().m_entries.at(index()).parameterOffset, + size}; + } + + /// @brief Get the covariance of the measurement + /// @return The covariance + CovarianceMatrixMap covariance() const { + const auto size = static_cast(this->size()); + return CovarianceMatrixMap{ + container().m_covariances.data() + + container().m_entries.at(index()).covarianceOffset, + size, size}; + } +}; } // namespace ActsExamples diff --git a/Examples/Framework/src/EventData/Measurement.cpp b/Examples/Framework/src/EventData/Measurement.cpp new file mode 100644 index 00000000000..d9ae3520d86 --- /dev/null +++ b/Examples/Framework/src/EventData/Measurement.cpp @@ -0,0 +1,75 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 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 http://mozilla.org/MPL/2.0/. + +#include "ActsExamples/EventData/Measurement.hpp" + +namespace ActsExamples { + +MeasurementContainer::MeasurementContainer() = default; + +std::size_t MeasurementContainer::size() const { + return m_entries.size(); +} + +void MeasurementContainer::reserve(std::size_t size) { + m_sourceLinks.reserve(size); + m_subspaceIndices.reserve(size * 2); + m_parameters.reserve(size * 2); + m_covariances.reserve(size * 2 * 2); +} + +std::size_t MeasurementContainer::addMeasurement(std::uint8_t size) { + m_entries.push_back({m_subspaceIndices.size(), m_parameters.size(), + m_covariances.size(), size}); + m_sourceLinks.emplace_back(); + m_subspaceIndices.resize(m_subspaceIndices.size() + size); + m_parameters.resize(m_parameters.size() + size); + m_covariances.resize(m_covariances.size() + size * size); + return m_entries.size() - 1; +} + +MeasurementContainer::VariableProxy MeasurementContainer::getMeasurement( + std::size_t index) { + return VariableProxy{*this, index}; +} + +MeasurementContainer::ConstVariableProxy MeasurementContainer::getMeasurement( + std::size_t index) const { + return ConstVariableProxy{*this, index}; +} + +MeasurementContainer::VariableProxy MeasurementContainer::makeMeasurement( + std::uint8_t size) { + return getMeasurement(addMeasurement(size)); +} + +MeasurementContainer::iterator MeasurementContainer::begin() { + return iterator{*this, 0}; +} + +MeasurementContainer::iterator MeasurementContainer::end() { + return iterator{*this, m_entries.size()}; +} + +MeasurementContainer::const_iterator MeasurementContainer::begin() const { + return const_iterator{*this, 0}; +} + +MeasurementContainer::const_iterator MeasurementContainer::end() const { + return const_iterator{*this, m_entries.size()}; +} + +MeasurementContainer::const_iterator MeasurementContainer::cbegin() const { + return const_iterator{*this, 0}; +} + +MeasurementContainer::const_iterator MeasurementContainer::cend() const { + return const_iterator{*this, m_entries.size()}; +} + +} // namespace ActsExamples diff --git a/Examples/Framework/src/EventData/MeasurementCalibration.cpp b/Examples/Framework/src/EventData/MeasurementCalibration.cpp index 560593dbd1f..84b1c5a2d45 100644 --- a/Examples/Framework/src/EventData/MeasurementCalibration.cpp +++ b/Examples/Framework/src/EventData/MeasurementCalibration.cpp @@ -6,11 +6,12 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +#include "ActsExamples/EventData/MeasurementCalibration.hpp" + #include "Acts/Definitions/TrackParametrization.hpp" #include "Acts/EventData/SourceLink.hpp" #include "ActsExamples/EventData/IndexSourceLink.hpp" #include "ActsExamples/EventData/Measurement.hpp" -#include #include #include @@ -31,18 +32,19 @@ void ActsExamples::PassThroughCalibrator::calibrate( assert((idxSourceLink.index() < measurements.size()) && "Source link index is outside the container bounds"); - const auto& measurement = measurements[idxSourceLink.index()]; + const ConstVariableBoundMeasurementProxy measurement = + measurements.getMeasurement(idxSourceLink.index()); Acts::visit_measurement(measurement.size(), [&](auto N) -> void { constexpr std::size_t kMeasurementSize = decltype(N)::value; + const ConstFixedBoundMeasurementProxy fixedMeasurement = + measurement; trackState.allocateCalibrated(kMeasurementSize); - trackState.calibrated() = - measurement.parameters(); + trackState.calibrated() = fixedMeasurement.parameters(); trackState.calibratedCovariance() = - measurement.covariance(); - trackState.setSubspaceIndices( - measurement.subspaceIndices()); + fixedMeasurement.covariance(); + trackState.setSubspaceIndices(fixedMeasurement.subspaceIndices()); }); } diff --git a/Examples/Framework/src/EventData/ScalingCalibrator.cpp b/Examples/Framework/src/EventData/ScalingCalibrator.cpp index 805d8cdef15..183dc3cb7d0 100644 --- a/Examples/Framework/src/EventData/ScalingCalibrator.cpp +++ b/Examples/Framework/src/EventData/ScalingCalibrator.cpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2023 CERN for the benefit of the Acts project +// Copyright (C) 2023-2024 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 @@ -151,7 +151,8 @@ void ActsExamples::ScalingCalibrator::calibrate( const Cluster& cl = clusters->at(idxSourceLink.index()); ConstantTuple ct = m_calib_maps.at(mgid).at(cl.sizeLoc0, cl.sizeLoc1); - const auto& measurement = measurements[idxSourceLink.index()]; + const ConstVariableBoundMeasurementProxy measurement = + measurements.getMeasurement(idxSourceLink.index()); assert(measurement.contains(Acts::eBoundLoc0) && "Measurement does not contain the required bound loc0"); @@ -161,21 +162,24 @@ void ActsExamples::ScalingCalibrator::calibrate( auto boundLoc0 = measurement.indexOf(Acts::eBoundLoc0); auto boundLoc1 = measurement.indexOf(Acts::eBoundLoc1); - Measurement measurementCopy = measurement; - measurementCopy.parameters()[boundLoc0] += ct.x_offset; - measurementCopy.parameters()[boundLoc1] += ct.y_offset; - measurementCopy.covariance()(boundLoc0, boundLoc0) *= ct.x_scale; - measurementCopy.covariance()(boundLoc1, boundLoc1) *= ct.y_scale; - Acts::visit_measurement(measurement.size(), [&](auto N) -> void { constexpr std::size_t kMeasurementSize = decltype(N)::value; + const ConstFixedBoundMeasurementProxy fixedMeasurement = + measurement; + + Acts::ActsVector calibratedParameters = + fixedMeasurement.parameters(); + Acts::ActsSquareMatrix calibratedCovariance = + fixedMeasurement.covariance(); + + calibratedParameters[boundLoc0] += ct.x_offset; + calibratedParameters[boundLoc1] += ct.y_offset; + calibratedCovariance(boundLoc0, boundLoc0) *= ct.x_scale; + calibratedCovariance(boundLoc1, boundLoc1) *= ct.y_scale; trackState.allocateCalibrated(kMeasurementSize); - trackState.calibrated() = - measurementCopy.parameters(); - trackState.calibratedCovariance() = - measurementCopy.covariance(); - trackState.setSubspaceIndices( - measurementCopy.subspaceIndices()); + trackState.calibrated() = calibratedParameters; + trackState.calibratedCovariance() = calibratedCovariance; + trackState.setSubspaceIndices(fixedMeasurement.subspaceIndices()); }); } diff --git a/Examples/Io/Csv/src/CsvMeasurementReader.cpp b/Examples/Io/Csv/src/CsvMeasurementReader.cpp index e1c31d52b63..ee036ea86a9 100644 --- a/Examples/Io/Csv/src/CsvMeasurementReader.cpp +++ b/Examples/Io/Csv/src/CsvMeasurementReader.cpp @@ -193,11 +193,14 @@ ActsExamples::ProcessCode ActsExamples::CsvMeasurementReader::read( readMeasurementsByGeometryId(m_cfg.inputDir, ctx.eventNumber); // Prepare containers for the hit data using the framework event data types - GeometryIdMultimap orderedMeasurements; + MeasurementContainer tmpMeasurements; + GeometryIdMultimap orderedMeasurements; IndexMultimap measurementSimHitsMap; IndexSourceLinkContainer sourceLinks; // need list here for stable addresses std::list sourceLinkStorage; + + tmpMeasurements.reserve(measurementData.size()); orderedMeasurements.reserve(measurementData.size()); // Safe long as we have single particle to sim hit association measurementSimHitsMap.reserve(measurementData.size()); @@ -251,14 +254,15 @@ ActsExamples::ProcessCode ActsExamples::CsvMeasurementReader::read( // the measurement will be stored is known before adding it. const Index index = orderedMeasurements.size(); IndexSourceLink& sourceLink = sourceLinkStorage.emplace_back(geoId, index); - auto measurement = createMeasurement(dParameters, sourceLink); + auto measurement = + createMeasurement(tmpMeasurements, dParameters, sourceLink); // Due to the previous sorting of the raw hit data by geometry id, new // measurements should always end up at the end of the container. previous // elements were not touched; cluster indices remain stable and can // be used to identify the m. - auto inserted = orderedMeasurements.emplace_hint( - orderedMeasurements.end(), geoId, std::move(measurement)); + auto inserted = orderedMeasurements.emplace_hint(orderedMeasurements.end(), + geoId, measurement); if (std::next(inserted) != orderedMeasurements.end()) { ACTS_FATAL("Something went horribly wrong with the hit sorting"); return ProcessCode::ABORT; @@ -269,7 +273,8 @@ ActsExamples::ProcessCode ActsExamples::CsvMeasurementReader::read( MeasurementContainer measurements; for (auto& [_, meas] : orderedMeasurements) { - measurements.emplace_back(std::move(meas)); + auto measurement = measurements.makeMeasurement(meas.size()); + measurement.copyFrom(meas); } // Generate measurement-particles-map diff --git a/Examples/Io/Csv/src/CsvMeasurementWriter.cpp b/Examples/Io/Csv/src/CsvMeasurementWriter.cpp index 0f65fca0d20..f31c812ba46 100644 --- a/Examples/Io/Csv/src/CsvMeasurementWriter.cpp +++ b/Examples/Io/Csv/src/CsvMeasurementWriter.cpp @@ -14,6 +14,7 @@ #include "ActsExamples/EventData/Cluster.hpp" #include "ActsExamples/EventData/Index.hpp" #include "ActsExamples/EventData/IndexSourceLink.hpp" +#include "ActsExamples/EventData/Measurement.hpp" #include "ActsExamples/Framework/AlgorithmContext.hpp" #include "ActsExamples/Io/Csv/CsvInputOutput.hpp" #include "ActsExamples/Utilities/Paths.hpp" @@ -92,7 +93,8 @@ ActsExamples::ProcessCode ActsExamples::CsvMeasurementWriter::writeT( << " measurements in this event."); for (Index measIdx = 0u; measIdx < measurements.size(); ++measIdx) { - const auto& measurement = measurements[measIdx]; + const ConstVariableBoundMeasurementProxy measurement = + measurements.getMeasurement(measIdx); auto simHitIndices = makeRange(measurementSimHitsMap.equal_range(measIdx)); for (auto [_, simHitIdx] : simHitIndices) { diff --git a/Examples/Io/EDM4hep/include/ActsExamples/Io/EDM4hep/EDM4hepUtil.hpp b/Examples/Io/EDM4hep/include/ActsExamples/Io/EDM4hep/EDM4hepUtil.hpp index 432f5a28323..6e6bac7a154 100644 --- a/Examples/Io/EDM4hep/include/ActsExamples/Io/EDM4hep/EDM4hepUtil.hpp +++ b/Examples/Io/EDM4hep/include/ActsExamples/Io/EDM4hep/EDM4hepUtil.hpp @@ -91,10 +91,10 @@ void writeSimHit(const ActsFatras::Hit& from, edm4hep::MutableSimTrackerHit to, /// Known issues: /// - cluster channels are read from inappropriate fields /// - local 2D coordinates and time are read from position -Measurement readMeasurement(const edm4hep::TrackerHitPlane& from, - const edm4hep::TrackerHitCollection* fromClusters, - Cluster* toCluster, - const MapGeometryIdFrom& geometryMapper); +VariableBoundMeasurementProxy readMeasurement( + MeasurementContainer& container, const edm4hep::TrackerHitPlane& from, + const edm4hep::TrackerHitCollection* fromClusters, Cluster* toCluster, + const MapGeometryIdFrom& geometryMapper); /// Writes a measurement cluster to EDM4hep. /// @@ -106,7 +106,7 @@ Measurement readMeasurement(const edm4hep::TrackerHitPlane& from, /// Known issues: /// - cluster channels are written to inappropriate fields /// - local 2D coordinates and time are written to position -void writeMeasurement(const Measurement& from, +void writeMeasurement(const ConstVariableBoundMeasurementProxy& from, edm4hep::MutableTrackerHitPlane to, const Cluster* fromCluster, edm4hep::TrackerHitCollection& toClusters, diff --git a/Examples/Io/EDM4hep/src/EDM4hepMeasurementReader.cpp b/Examples/Io/EDM4hep/src/EDM4hepMeasurementReader.cpp index f24e64ccd8e..19606206e0e 100644 --- a/Examples/Io/EDM4hep/src/EDM4hepMeasurementReader.cpp +++ b/Examples/Io/EDM4hep/src/EDM4hepMeasurementReader.cpp @@ -66,11 +66,10 @@ ProcessCode EDM4hepMeasurementReader::read(const AlgorithmContext& ctx) { for (const auto& trackerHitPlane : trackerHitPlaneCollection) { Cluster cluster; - auto measurement = EDM4hepUtil::readMeasurement( - trackerHitPlane, &trackerHitRawCollection, &cluster, + EDM4hepUtil::readMeasurement( + measurements, trackerHitPlane, &trackerHitRawCollection, &cluster, [](std::uint64_t cellId) { return Acts::GeometryIdentifier(cellId); }); - measurements.push_back(std::move(measurement)); clusters.push_back(std::move(cluster)); } diff --git a/Examples/Io/EDM4hep/src/EDM4hepMeasurementWriter.cpp b/Examples/Io/EDM4hep/src/EDM4hepMeasurementWriter.cpp index 6b26db80362..f9b35e7edb1 100644 --- a/Examples/Io/EDM4hep/src/EDM4hepMeasurementWriter.cpp +++ b/Examples/Io/EDM4hep/src/EDM4hepMeasurementWriter.cpp @@ -55,7 +55,8 @@ ActsExamples::ProcessCode EDM4hepMeasurementWriter::writeT( << " measurements in this event."); for (Index hitIdx = 0u; hitIdx < measurements.size(); ++hitIdx) { - const auto& from = measurements[hitIdx]; + ConstVariableBoundMeasurementProxy from = + measurements.getMeasurement(hitIdx); const Cluster* fromCluster = clusters.empty() ? nullptr : &clusters[hitIdx]; auto to = hitsPlane.create(); diff --git a/Examples/Io/EDM4hep/src/EDM4hepUtil.cpp b/Examples/Io/EDM4hep/src/EDM4hepUtil.cpp index 6a7adfe98c5..dc863b135ab 100644 --- a/Examples/Io/EDM4hep/src/EDM4hepUtil.cpp +++ b/Examples/Io/EDM4hep/src/EDM4hepUtil.cpp @@ -18,6 +18,7 @@ #include "ActsExamples/Digitization/MeasurementCreation.hpp" #include "ActsExamples/EventData/Index.hpp" #include "ActsExamples/EventData/IndexSourceLink.hpp" +#include "ActsExamples/EventData/Measurement.hpp" #include "ActsExamples/EventData/SimHit.hpp" #include "ActsExamples/Validation/TrackClassification.hpp" @@ -144,8 +145,8 @@ void EDM4hepUtil::writeSimHit(const ActsFatras::Hit& from, to.setEDep(-delta4[Acts::eEnergy] / Acts::UnitConstants::GeV); } -Measurement EDM4hepUtil::readMeasurement( - const edm4hep::TrackerHitPlane& from, +VariableBoundMeasurementProxy EDM4hepUtil::readMeasurement( + MeasurementContainer& container, const edm4hep::TrackerHitPlane& from, const edm4hep::TrackerHitCollection* fromClusters, Cluster* toCluster, const MapGeometryIdFrom& geometryMapper) { // no need for digitization as we only want to identify the sensor @@ -172,7 +173,7 @@ Measurement EDM4hepUtil::readMeasurement( dParameters.values.push_back(pos.z); dParameters.variances.push_back(cov[5]); - auto to = createMeasurement(dParameters, sourceLink); + auto to = createMeasurement(container, dParameters, sourceLink); if (fromClusters != nullptr) { for (const auto objectId : from.getRawHits()) { @@ -196,11 +197,11 @@ Measurement EDM4hepUtil::readMeasurement( return to; } -void EDM4hepUtil::writeMeasurement(const Measurement& from, - edm4hep::MutableTrackerHitPlane to, - const Cluster* fromCluster, - edm4hep::TrackerHitCollection& toClusters, - const MapGeometryIdTo& geometryMapper) { +void EDM4hepUtil::writeMeasurement( + const ConstVariableBoundMeasurementProxy& from, + edm4hep::MutableTrackerHitPlane to, const Cluster* fromCluster, + edm4hep::TrackerHitCollection& toClusters, + const MapGeometryIdTo& geometryMapper) { Acts::GeometryIdentifier geoId = from.sourceLink().template get().geometryId(); diff --git a/Examples/Io/Root/src/RootAthenaDumpReader.cpp b/Examples/Io/Root/src/RootAthenaDumpReader.cpp index 8300237ef9e..001a8d90bdb 100644 --- a/Examples/Io/Root/src/RootAthenaDumpReader.cpp +++ b/Examples/Io/Root/src/RootAthenaDumpReader.cpp @@ -372,7 +372,7 @@ ActsExamples::ProcessCode ActsExamples::RootAthenaDumpReader::read( IndexSourceLink sl(Acts::GeometryIdentifier{CLmoduleID[im]}, im); - measurements.push_back(createMeasurement(digiPars, sl)); + createMeasurement(measurements, digiPars, sl); // Create measurement particles map and particles container for (const auto& [subevt, bc] : Acts::zip(CLparticleLink_eventIndex->at(im), diff --git a/Examples/Io/Root/src/RootMeasurementWriter.cpp b/Examples/Io/Root/src/RootMeasurementWriter.cpp index 6dc10e3b4b1..88b66e192f0 100644 --- a/Examples/Io/Root/src/RootMeasurementWriter.cpp +++ b/Examples/Io/Root/src/RootMeasurementWriter.cpp @@ -13,6 +13,7 @@ #include "ActsExamples/EventData/AverageSimHits.hpp" #include "ActsExamples/EventData/Index.hpp" #include "ActsExamples/EventData/IndexSourceLink.hpp" +#include "ActsExamples/EventData/Measurement.hpp" #include "ActsExamples/Framework/AlgorithmContext.hpp" #include "ActsExamples/Utilities/Range.hpp" @@ -152,9 +153,9 @@ struct RootMeasurementWriter::DigitizationTree { /// Convenience function to fill bound parameters /// /// @param m The measurement - void fillBoundMeasurement(const Measurement& m) { + void fillBoundMeasurement(const ConstVariableBoundMeasurementProxy& m) { for (unsigned int i = 0; i < m.size(); ++i) { - auto ib = m.subspaceIndices()[i]; + auto ib = m.subspaceIndexVector()[i]; recBound[ib] = m.parameters()[i]; varBound[ib] = m.covariance()(i, i); @@ -266,7 +267,8 @@ ProcessCode RootMeasurementWriter::writeT( std::lock_guard lock(m_writeMutex); for (Index hitIdx = 0u; hitIdx < measurements.size(); ++hitIdx) { - const auto& meas = measurements[hitIdx]; + const ConstVariableBoundMeasurementProxy meas = + measurements.getMeasurement(hitIdx); Acts::GeometryIdentifier geoId = meas.sourceLink().template get().geometryId(); diff --git a/Examples/Io/Root/src/RootPropagationStepsWriter.cpp b/Examples/Io/Root/src/RootPropagationStepsWriter.cpp index 5f157d519d6..13e37f44e65 100644 --- a/Examples/Io/Root/src/RootPropagationStepsWriter.cpp +++ b/Examples/Io/Root/src/RootPropagationStepsWriter.cpp @@ -135,6 +135,7 @@ ActsExamples::ProcessCode ActsExamples::RootPropagationStepsWriter::writeT( m_x.clear(); m_y.clear(); m_z.clear(); + m_r.clear(); m_dx.clear(); m_dy.clear(); m_dz.clear(); diff --git a/Examples/Io/Root/src/RootTrackStatesWriter.cpp b/Examples/Io/Root/src/RootTrackStatesWriter.cpp index 2718ab37cd9..55947c67f7a 100644 --- a/Examples/Io/Root/src/RootTrackStatesWriter.cpp +++ b/Examples/Io/Root/src/RootTrackStatesWriter.cpp @@ -486,7 +486,8 @@ ProcessCode RootTrackStatesWriter::writeT(const AlgorithmContext& ctx, if (ipar == eSmoothed && state.hasSmoothed()) { return std::make_pair(state.smoothed(), state.smoothedCovariance()); } - if (ipar == eUnbiased && state.hasSmoothed() && state.hasProjector()) { + if (ipar == eUnbiased && state.hasSmoothed() && state.hasProjector() && + state.hasCalibrated()) { // calculate the unbiased track parameters (i.e. fitted track // parameters with this measurement removed) using Eq.(12a)-Eq.(12c) // of NIMA 262, 444 (1987) diff --git a/Examples/Python/CMakeLists.txt b/Examples/Python/CMakeLists.txt index 13408e53f1d..ff1e5901f43 100644 --- a/Examples/Python/CMakeLists.txt +++ b/Examples/Python/CMakeLists.txt @@ -99,9 +99,12 @@ if(ACTS_BUILD_PLUGIN_TRACCC) target_sources(ActsPythonBindings PRIVATE src/Detray.cpp) target_link_libraries(ActsPythonBindings PUBLIC ActsPluginCovfie) target_sources(ActsPythonBindings PRIVATE src/Covfie.cpp) + target_link_libraries(ActsPythonBindings PUBLIC ActsExamplesTraccc) + target_sources(ActsPythonBindings PRIVATE src/Traccc.cpp) else() target_sources(ActsPythonBindings PRIVATE src/DetrayStub.cpp) target_sources(ActsPythonBindings PRIVATE src/CovfieStub.cpp) + target_sources(ActsPythonBindings PRIVATE src/TracccStub.cpp) endif() if(ACTS_BUILD_PLUGIN_ACTSVG) diff --git a/Examples/Python/src/Detray.cpp b/Examples/Python/src/Detray.cpp index 5239ad3ce36..d254a51443d 100644 --- a/Examples/Python/src/Detray.cpp +++ b/Examples/Python/src/Detray.cpp @@ -30,12 +30,42 @@ namespace Acts::Python { void addDetray(Context& ctx) { auto [m, mex] = ctx.get("main", "examples"); + auto detray = m.def_submodule("detray"); { py::class_, - std::shared_ptr>>(m, + std::shared_ptr>>(detray, "detray_detector"); } - { mex.def("writeToJson", &DetrayConverter::writeToJson); } + { + // This test function will convert an ACTS detector into a detray detector + // and write it to the corresponding json files. + // + // The memory resource and the detector are destroyed after the function + detray.def("writeToJson", [](const GeometryContext& gctx, + const Experimental::Detector& detector) { + auto memoryResource = vecmem::host_memory_resource(); + + DetrayConverter::Options options; + options.writeToJson = true; + options.convertMaterial = false; + options.convertSurfaceGrids = true; + auto DetrayHostDetector = + DetrayConverter().convert<>(gctx, detector, memoryResource, options); + }); + } + + { + auto converter = py::class_(detray, "DetrayConverter"); + + auto options = py::class_(converter, "Options") + .def(py::init<>()); + + ACTS_PYTHON_STRUCT_BEGIN(options, DetrayConverter::Options); + ACTS_PYTHON_MEMBER(convertMaterial); + ACTS_PYTHON_MEMBER(convertSurfaceGrids); + ACTS_PYTHON_MEMBER(writeToJson); + ACTS_PYTHON_STRUCT_END(); + } } } // namespace Acts::Python diff --git a/Examples/Python/src/ModuleEntry.cpp b/Examples/Python/src/ModuleEntry.cpp index 6edb715e0cd..791eabc327b 100644 --- a/Examples/Python/src/ModuleEntry.cpp +++ b/Examples/Python/src/ModuleEntry.cpp @@ -83,6 +83,7 @@ void addObj(Context& ctx); void addOnnx(Context& ctx); void addOnnxNeuralCalibrator(Context& ctx); void addCovfie(Context& ctx); +void addTraccc(Context& ctx); void addHashing(Context& ctx); } // namespace Acts::Python @@ -151,5 +152,6 @@ PYBIND11_MODULE(ActsPythonBindings, m) { addOnnx(ctx); addOnnxNeuralCalibrator(ctx); addCovfie(ctx); + addTraccc(ctx); addHashing(ctx); } diff --git a/Examples/Python/src/Traccc.cpp b/Examples/Python/src/Traccc.cpp new file mode 100644 index 00000000000..d620a5584f7 --- /dev/null +++ b/Examples/Python/src/Traccc.cpp @@ -0,0 +1,92 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 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 http://mozilla.org/MPL/2.0/. + +// This file is part of the Acts project. +// +// Copyright (C) 2024 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 http://mozilla.org/MPL/2.0/. + +#include "Acts/Plugins/Detray/DetrayConversionUtils.hpp" +#include "Acts/Plugins/Detray/DetrayConverter.hpp" +#include "Acts/Plugins/Python/Utilities.hpp" +#include "ActsExamples/Propagation/PropagatorInterface.hpp" +#include "ActsExamples/Traccc/DetrayPropagator.hpp" +#include "ActsExamples/Traccc/DetrayStore.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace py = pybind11; +using namespace pybind11::literals; + +using namespace Acts; +using namespace ActsExamples; + +namespace Acts::Python { + +void addTraccc(Context& ctx) { + auto [m, mex] = ctx.get("main", "examples"); + + auto traccc = mex.def_submodule("traccc"); + + /// Define host detray store + { + py::class_>( + traccc, "DetrayHostStore"); + + /// Convert the detector and create a DetrayHostStore + /// + /// @param gctx the geometry context + /// @param detector the detector to be converted + /// @param options the conversion options + traccc.def("convertDetectorHost", [](const GeometryContext& gctx, + const Experimental::Detector& detector, + DetrayConverter::Options options) { + return DetrayHostStore::create(gctx, detector, options); + }); + } + + /// Define the DetrayPropagator + { + traccc.def("createPropagatorHost", [](std::shared_ptr + detrayStore) { + std::shared_ptr detrayProagator = nullptr; + + /// Aggregation of multiple inspectors + using DetrayInspector = + detray::aggregate_inspector; + + // Navigation with inspection + using DetrayNavigator = + detray::navigator; + // Line stepper + using DetrayLineStepper = + detray::line_stepper; + + // Propagator with empty actor chain + using Propagator = detray::propagator>; + + Propagator propagator; + detrayProagator = + std::make_shared>( + std::move(propagator), detrayStore); + return detrayProagator; + }); + } +} +} // namespace Acts::Python diff --git a/Examples/Python/src/TracccStub.cpp b/Examples/Python/src/TracccStub.cpp new file mode 100644 index 00000000000..65b802a77b4 --- /dev/null +++ b/Examples/Python/src/TracccStub.cpp @@ -0,0 +1,13 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 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 http://mozilla.org/MPL/2.0/. + +#include "Acts/Plugins/Python/Utilities.hpp" + +namespace Acts::Python { +void addTraccc(Context& /*ctx*/) {} +} // namespace Acts::Python diff --git a/Examples/Python/tests/root_file_hashes.txt b/Examples/Python/tests/root_file_hashes.txt index e8b70a79bab..88d903b6f1e 100644 --- a/Examples/Python/tests/root_file_hashes.txt +++ b/Examples/Python/tests/root_file_hashes.txt @@ -56,9 +56,9 @@ test_vertex_fitting_reading[AMVF-False-100]__performance_vertexing.root: 009e4b1 test_vertex_fitting_reading[AMVF-True-100]__performance_vertexing.root: 2d0dc1e02bfd1f7eaae26ef8ac657ce0291f70c7e4efddd35d171d31988a631e test_bfield_writing__solenoid.root: 7be51f0ed9cb99f59ae0271ba79cdb84635e6ee3d2109ea8a4b521875029c21d test_bfield_writing__solenoid2.root: 2db149336c9cd749dc50025076b49f9bc0586d53792b87a0fdd7f21a649a01a5 -test_root_prop_step_writer[configPosConstructor]__prop_steps.root: c0a4898c1f2539d9e3e72587d5a377fc700fed6deb156952daeff670ab7a6f55 -test_root_prop_step_writer[configKwConstructor]__prop_steps.root: c0a4898c1f2539d9e3e72587d5a377fc700fed6deb156952daeff670ab7a6f55 -test_root_prop_step_writer[kwargsConstructor]__prop_steps.root: c0a4898c1f2539d9e3e72587d5a377fc700fed6deb156952daeff670ab7a6f55 +test_root_prop_step_writer[configPosConstructor]__prop_steps.root: a783d525eebb4737e6e6bcf20d63d6f35520f4bcf23301ae8c4657309cbccdda +test_root_prop_step_writer[configKwConstructor]__prop_steps.root: a783d525eebb4737e6e6bcf20d63d6f35520f4bcf23301ae8c4657309cbccdda +test_root_prop_step_writer[kwargsConstructor]__prop_steps.root: a783d525eebb4737e6e6bcf20d63d6f35520f4bcf23301ae8c4657309cbccdda test_root_particle_writer[configPosConstructor]__particles.root: 759f7c0225a30afc28c3dda6010295207254ebb0194b88f692d538b8c65d4326 test_root_particle_writer[configKwConstructor]__particles.root: 759f7c0225a30afc28c3dda6010295207254ebb0194b88f692d538b8c65d4326 test_root_particle_writer[kwargsConstructor]__particles.root: 759f7c0225a30afc28c3dda6010295207254ebb0194b88f692d538b8c65d4326 diff --git a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConversionUtils.hpp b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConversionUtils.hpp index 6e5a6788a63..f3a111f7aee 100644 --- a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConversionUtils.hpp +++ b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConversionUtils.hpp @@ -20,20 +20,10 @@ namespace Acts { -using DetrayDetector = detray::detector; +using DetrayHostDetector = detray::detector; namespace DetrayConversionUtils { -/// Detray conversion options -struct Options { - /// Option to switch on/off the material conversion - bool convertMaterial = true; - /// Option to switch on/off the surface grid conversin - bool convertSurfaceGrids = true; - /// Option to switch on/off the export to json - bool writeToJson = false; -}; - /// Detray conversion cache object /// /// This object is used to synchronize link information between the diff --git a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConverter.hpp b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConverter.hpp index ffb799cc29b..24c59968ec5 100644 --- a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConverter.hpp +++ b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConverter.hpp @@ -26,6 +26,16 @@ using namespace Experimental; class DetrayConverter { public: + /// Detray conversion options + struct Options { + /// Option to switch on/off the material conversion + bool convertMaterial = true; + /// Option to switch on/off the surface grid conversin + bool convertSurfaceGrids = true; + /// Option to switch on/off the export to json + bool writeToJson = false; + }; + /// Constructor with logger DetrayConverter(std::unique_ptr logger = getDefaultLogger("DetrayConverter", Logging::INFO)); @@ -38,11 +48,9 @@ class DetrayConverter { /// @param options the conversion options /// /// @returns a detector of requested return type - template - detector_t convert( - const GeometryContext& gctx, const Detector& detector, - vecmem::memory_resource& mr, - [[maybe_unused]] const DetrayConversionUtils::Options& options = {}) { + template + detector_t convert(const GeometryContext& gctx, const Detector& detector, + vecmem::memory_resource& mr, const Options& options) { // The building cache object DetrayConversionUtils::GeometryIdCache geoIdCache; @@ -56,16 +64,30 @@ class DetrayConverter { logger()); detray::io::geometry_reader::convert(detectorBuilder, names, detectorPayload); - // (2) material + + // (2a) homogeneous material + if constexpr (detray::detail::has_homogeneous_material_v) { + if (options.convertMaterial) { + detray::io::detector_homogeneous_material_payload materialSlabsPayload = + DetrayMaterialConverter::convertHomogeneousSurfaceMaterial( + geoIdCache, detector, logger()); + detray::io::homogeneous_material_reader::convert( + detectorBuilder, names, std::move(materialSlabsPayload)); + } + } + + // (2b) material grids if constexpr (detray::detail::has_material_grids_v) { if (options.convertMaterial) { detray::io::detector_grids_payload - materialPayload = - DetrayMaterialConverter::convertSurfaceMaterialGrids( + materialGridsPayload = + DetrayMaterialConverter::convertGridSurfaceMaterial( geoIdCache, detector, logger()); - detray::io::material_map_reader<>::convert( - detectorBuilder, names, materialPayload); + detray::io::material_map_reader>::convert(detectorBuilder, names, + std::move( + materialGridsPayload)); } } @@ -91,9 +113,10 @@ class DetrayConverter { /// @param dDetector is the detray detector (converted) /// @param names a name map for the detector volumes /// @param writer_cfg the writer configuration - static void writeToJson(const DetrayDetector& dDetector, - const typename DetrayDetector::name_map& names = {}, - detray::io::detector_writer_config writer_cfg = {}); + static void writeToJson( + const DetrayHostDetector& dDetector, + const typename DetrayHostDetector::name_map& names = {}, + detray::io::detector_writer_config writer_cfg = {}); private: /// The logger instance diff --git a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayMaterialConverter.hpp b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayMaterialConverter.hpp index d0edc1beda7..fecdec364b8 100644 --- a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayMaterialConverter.hpp +++ b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayMaterialConverter.hpp @@ -8,6 +8,7 @@ #pragma once +#include "Acts/Material/HomogeneousSurfaceMaterial.hpp" #include "Acts/Material/ISurfaceMaterial.hpp" #include "Acts/Material/MaterialSlab.hpp" #include "Acts/Plugins/Detray/DetrayConversionUtils.hpp" @@ -32,16 +33,28 @@ namespace DetrayMaterialConverter { detray::io::material_slab_payload convertMaterialSlab( const MaterialSlab& materialSlab); -/// Conversion method for surface material objects +/// Conversion method for homogeneous material /// +/// @param geoIdCache object to have the link association from the geometry building /// @param detector the detector object /// @param logger the logger object for screen output /// +/// @return the volume_payload for portals and volumes by @param volume acts object +detray::io::detector_homogeneous_material_payload +convertHomogeneousSurfaceMaterial( + const DetrayConversionUtils::GeometryIdCache& geoIdCache, + const Experimental::Detector& detector, const Logger& logger); + +/// Conversion method for grid based surface material +/// +/// @param material the material (Binned/Grid) +/// @param logger the logger object for screen output +/// /// @return a surface material detray::io::grid_payload -convertSurfaceMaterial(const ISurfaceMaterial& material, - const Acts::Logger& logger); +convertGridSurfaceMaterial(const ISurfaceMaterial& material, + const Acts::Logger& logger); /// Conversion method for material grids /// @@ -52,7 +65,7 @@ convertSurfaceMaterial(const ISurfaceMaterial& material, /// @return the volume_payload for portals and volumes by @param volume acts object detray::io::detector_grids_payload -convertSurfaceMaterialGrids( +convertGridSurfaceMaterial( const DetrayConversionUtils::GeometryIdCache& geoIdCache, const Experimental::Detector& detector, const Logger& logger); diff --git a/Plugins/Detray/src/DetrayConverter.cpp b/Plugins/Detray/src/DetrayConverter.cpp index 3b72b998ab5..d35ff7cb6ba 100644 --- a/Plugins/Detray/src/DetrayConverter.cpp +++ b/Plugins/Detray/src/DetrayConverter.cpp @@ -13,8 +13,8 @@ Acts::DetrayConverter::DetrayConverter( : m_logger(std::move(logger)) {} void Acts::DetrayConverter::writeToJson( - const DetrayDetector& dDetector, - const typename DetrayDetector::name_map& names, + const DetrayHostDetector& dDetector, + const typename DetrayHostDetector::name_map& names, detray::io::detector_writer_config writer_cfg) { writer_cfg.format(detray::io::format::json); detray::io::write_detector(dDetector, names, writer_cfg); diff --git a/Plugins/Detray/src/DetrayGeometryConverter.cpp b/Plugins/Detray/src/DetrayGeometryConverter.cpp index 9e531e0be21..4c1902c6b13 100644 --- a/Plugins/Detray/src/DetrayGeometryConverter.cpp +++ b/Plugins/Detray/src/DetrayGeometryConverter.cpp @@ -47,10 +47,9 @@ int findVolume( detray::io::transform_payload Acts::DetrayGeometryConverter::convertTransform( const Transform3& t) { detray::io::transform_payload tfPayload; - auto translation = t.translation(); + Vector3 translation = t.translation(); tfPayload.tr = {translation.x(), translation.y(), translation.z()}; - - const auto rotation = t.rotation(); + RotationMatrix3 rotation = t.rotation().transpose(); tfPayload.rot = {rotation(0, 0), rotation(0, 1), rotation(0, 2), rotation(1, 0), rotation(1, 1), rotation(1, 2), rotation(2, 0), rotation(2, 1), rotation(2, 2)}; @@ -260,7 +259,7 @@ Acts::DetrayGeometryConverter::convertPortal( // Write surface with invalid link auto portalPayload = convertSurface(gctx, *surfaceAdjusted, true); using NavigationLink = - typename DetrayDetector::surface_type::navigation_link; + typename DetrayHostDetector::surface_type::navigation_link; portalPayload.mask.volume_link.link = std::numeric_limits::max(); diff --git a/Plugins/Detray/src/DetrayMaterialConverter.cpp b/Plugins/Detray/src/DetrayMaterialConverter.cpp index eefd2c59712..14fdd2163df 100644 --- a/Plugins/Detray/src/DetrayMaterialConverter.cpp +++ b/Plugins/Detray/src/DetrayMaterialConverter.cpp @@ -11,6 +11,7 @@ #include "Acts/Detector/Detector.hpp" #include "Acts/Material/BinnedSurfaceMaterial.hpp" #include "Acts/Material/HomogeneousSurfaceMaterial.hpp" +#include "Acts/Material/ProtoSurfaceMaterial.hpp" #include "Acts/Plugins/Detray/DetrayConversionUtils.hpp" #include "Acts/Surfaces/Surface.hpp" #include "Acts/Utilities/BinUtility.hpp" @@ -34,19 +35,6 @@ struct MaterialSurfaceSelector { } }; -/// This creates dummy axes to allow homogeneous material for the moment -/// to be represented as grid surface material -std::vector homogeneousAxesPayloads() { - Acts::BinningData bDataX(Acts::BinningValue::binX, -1, 1); - bDataX.option = Acts::BinningOption::closed; - Acts::BinningData bDataY(Acts::BinningValue::binY, -1, 1); - bDataY.option = Acts::BinningOption::closed; - auto axisPayloadX = Acts::DetrayConversionUtils::convertBinningData(bDataX); - auto axisPayloadY = Acts::DetrayConversionUtils::convertBinningData(bDataY); - - return {axisPayloadX, axisPayloadY}; -} - } // namespace detray::io::material_slab_payload @@ -63,30 +51,77 @@ Acts::DetrayMaterialConverter::convertMaterialSlab( return slab; } +detray::io::detector_homogeneous_material_payload +Acts::DetrayMaterialConverter::convertHomogeneousSurfaceMaterial( + const DetrayConversionUtils::GeometryIdCache& geoIdCache, + const Experimental::Detector& detector, const Logger& logger) { + detray::io::detector_homogeneous_material_payload materialPayload; + + for (const auto volume : detector.volumes()) { + auto volumeIndex = geoIdCache.volumeLinks.find(volume->geometryId()); + if (volumeIndex != geoIdCache.volumeLinks.end()) { + // The volume material payload & its link + detray::io::material_volume_payload volumePayload; + detray::io::single_link_payload volumeLink; + volumeLink.link = volumeIndex->second; + volumePayload.volume_link = volumeLink; + // Now run through surfaces and portals to find the material + MaterialSurfaceSelector selector; + volume->visitSurfaces(selector); + ACTS_DEBUG("DetrayMaterialConverter: found " + << selector.surfaces.size() + << " surfaces/portals with material in volume " + << volume->name()); + for (const auto surface : selector.surfaces) { + const auto* surfaceMaterial = surface->surfaceMaterial(); + auto homogeneousMaterial = + dynamic_cast(surfaceMaterial); + if (homogeneousMaterial != nullptr) { + // Convert the material slab + auto materialSlab = homogeneousMaterial->materialSlab(); + detray::io::material_slab_payload slabPayload = + convertMaterialSlab(materialSlab); + // Find the surfaces and assign + auto surfaceIndices = + geoIdCache.localSurfaceLinks.equal_range(surface->geometryId()); + // Loop over the equal range and fill one grid each, this is needed + // as the initial portal could be split into multiple surfaces + for (auto itr = surfaceIndices.first; itr != surfaceIndices.second; + ++itr) { + // Make an identified link copy for every matching surface + detray::io::single_link_payload surfaceLink; + surfaceLink.link = itr->second; + slabPayload.surface = surfaceLink; + volumePayload.mat_slabs.push_back(slabPayload); + } + } + } + materialPayload.volumes.push_back(volumePayload); + } else { + ACTS_WARNING("DetrayMaterialConverter: volume " << volume->name() + << " not found in cache"); + } + } + + return materialPayload; +} + detray::io::grid_payload -Acts::DetrayMaterialConverter::convertSurfaceMaterial( +Acts::DetrayMaterialConverter::convertGridSurfaceMaterial( const ISurfaceMaterial& material, const Logger& logger) { detray::io::grid_payload materialGrid; // Check the material types - // (1) homogeneous -> 1 x 1 bin grid with closed axes + // (1) homogeneous -> skip auto homogeneousMaterial = dynamic_cast(&material); if (homogeneousMaterial != nullptr) { - ACTS_VERBOSE( - "DetrayMaterialConverter: found homogeneous surface material, this " - "will be modelled as a 1x1 bin grid"); - // A single bin entry: convert it and fill it - detray::io::material_slab_payload slab = convertMaterialSlab( - homogeneousMaterial->materialSlab(Vector3{0., 0., 0.})); - detray::io::grid_bin_payload slabBin{ - {0, 0}, {slab}}; - // Filling axes and bins - materialGrid.axes = homogeneousAxesPayloads(); - materialGrid.bins = {slabBin}; + ACTS_DEBUG( + "DetrayMaterialConverter: found homogeneous surface material, ignored " + "as this should be handled by the homogeneous material conversion."); return materialGrid; } // (2) - binned material -> convert into grid structure @@ -148,7 +183,8 @@ Acts::DetrayMaterialConverter::convertSurfaceMaterial( } else if (bVal0 == BinningValue::binX && bVal1 == BinningValue::binY) { gridIndexType = detray::io::material_id::rectangle2_map; } else { - std::runtime_error("Unsupported binning for Detray"); + std::runtime_error( + "DetrayMaterialConverter: Unsupported binning for Detray"); } detray::io::typed_link_payload linkPayload{ @@ -180,13 +216,23 @@ Acts::DetrayMaterialConverter::convertSurfaceMaterial( return materialGrid; } + if (dynamic_cast(&material) != nullptr || + dynamic_cast(&material) != + nullptr) { + ACTS_WARNING( + "DetrayMaterialConverter: ProtoSurfaceMaterial and " + "ProtoGridSurfaceMaterial are not being translated, consider to switch " + "material conversion off."); + return materialGrid; + } + throw std::invalid_argument( "DetrayMaterialConverter: unknown surface material type detected."); } detray::io::detector_grids_payload -Acts::DetrayMaterialConverter::convertSurfaceMaterialGrids( +Acts::DetrayMaterialConverter::convertGridSurfaceMaterial( const DetrayConversionUtils::GeometryIdCache& geoIdCache, const Experimental::Detector& detector, const Logger& logger) { // The material grid payload @@ -217,7 +263,11 @@ Acts::DetrayMaterialConverter::convertSurfaceMaterialGrids( auto surfaceIndices = geoIdCache.localSurfaceLinks.equal_range(surface->geometryId()); DetrayMaterialGrid materialGrid = - convertSurfaceMaterial(*surface->surfaceMaterial(), logger); + convertGridSurfaceMaterial(*surface->surfaceMaterial(), logger); + // Ignore if an empty payload is returned + if (materialGrid.axes.empty() && materialGrid.bins.empty()) { + continue; + } // Loop over the equal range and fill one grid each, this is needed // as the initial portal could be split into multiple surfaces for (auto itr = surfaceIndices.first; itr != surfaceIndices.second; diff --git a/Plugins/EDM4hep/include/Acts/Plugins/EDM4hep/EDM4hepUtil.hpp b/Plugins/EDM4hep/include/Acts/Plugins/EDM4hep/EDM4hepUtil.hpp index 505f9bbe1cc..9b55768f70b 100644 --- a/Plugins/EDM4hep/include/Acts/Plugins/EDM4hep/EDM4hepUtil.hpp +++ b/Plugins/EDM4hep/include/Acts/Plugins/EDM4hep/EDM4hepUtil.hpp @@ -14,6 +14,7 @@ #include "Acts/EventData/MultiTrajectory.hpp" #include "Acts/EventData/TrackContainer.hpp" #include "Acts/EventData/TrackParameters.hpp" +#include "Acts/EventData/TrackProxyConcept.hpp" #include "Acts/EventData/TrackStatePropMask.hpp" #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Surfaces/PerigeeSurface.hpp" @@ -60,14 +61,10 @@ BoundTrackParameters convertTrackParametersFromEdm4hep( } // namespace detail -template class holder_t> -void writeTrack( - const Acts::GeometryContext& gctx, - Acts::TrackProxy - track, - edm4hep::MutableTrack to, double Bz, - const Logger& logger = getDummyLogger()) { +template +void writeTrack(const Acts::GeometryContext& gctx, track_proxy_t track, + edm4hep::MutableTrack to, double Bz, + const Logger& logger = getDummyLogger()) { ACTS_VERBOSE("Converting track to EDM4hep"); to.setChi2(track.chi2()); to.setNdf(track.nDoF()); @@ -164,13 +161,9 @@ void writeTrack( } } -template class holder_t> -void readTrack(const edm4hep::Track& from, - Acts::TrackProxy - track, - double Bz, const Logger& logger = getDummyLogger()) { +template +void readTrack(const edm4hep::Track& from, track_proxy_t track, double Bz, + const Logger& logger = getDummyLogger()) { ACTS_VERBOSE("Reading track from EDM4hep"); TrackStatePropMask mask = TrackStatePropMask::Smoothed; diff --git a/Plugins/Onnx/include/Acts/Plugins/Onnx/AmbiguityTrackClassifier.hpp b/Plugins/Onnx/include/Acts/Plugins/Onnx/AmbiguityTrackClassifier.hpp index 8759450abd4..c2dd49c1294 100644 --- a/Plugins/Onnx/include/Acts/Plugins/Onnx/AmbiguityTrackClassifier.hpp +++ b/Plugins/Onnx/include/Acts/Plugins/Onnx/AmbiguityTrackClassifier.hpp @@ -10,6 +10,8 @@ #include "Acts/EventData/MultiTrajectoryHelpers.hpp" #include "Acts/EventData/TrackContainer.hpp" +#include "Acts/EventData/TrackContainerFrontendConcept.hpp" +#include "Acts/EventData/TrackProxyConcept.hpp" #include "Acts/Plugins/Onnx/OnnxRuntimeBase.hpp" #include "Acts/TrackFinding/detail/AmbiguityTrackClustering.hpp" @@ -36,12 +38,10 @@ class AmbiguityTrackClassifier { /// @param clusters is a map of clusters, each cluster correspond to a vector of track ID /// @param tracks is the input track container /// @return a vector of vector of track score. Due to the architecture of the network each track only have a size 1 score vector. - template class holder_t> + template std::vector> inferScores( std::unordered_map>& clusters, - const Acts::TrackContainer& tracks) - const { + const track_container_t& tracks) const { // Compute the number of entry (since it is smaller than the number of // track) int trackNb = 0; @@ -107,12 +107,10 @@ class AmbiguityTrackClassifier { /// @param clusters is a map of clusters, each cluster correspond to a vector of track ID /// @param tracks is the input track container /// @return a vector of trackID corresponding tho the good tracks - template class holder_t> + template std::vector solveAmbiguity( std::unordered_map>& clusters, - const Acts::TrackContainer& tracks) - const { + const track_container_t& tracks) const { std::vector> outputTensor = inferScores(clusters, tracks); std::vector goodTracks = diff --git a/Plugins/Podio/include/Acts/Plugins/Podio/PodioTrackContainer.hpp b/Plugins/Podio/include/Acts/Plugins/Podio/PodioTrackContainer.hpp index 8ef787b32c4..a4c71eb2c7c 100644 --- a/Plugins/Podio/include/Acts/Plugins/Podio/PodioTrackContainer.hpp +++ b/Plugins/Podio/include/Acts/Plugins/Podio/PodioTrackContainer.hpp @@ -15,6 +15,7 @@ #include "Acts/EventData/detail/DynamicColumn.hpp" #include "Acts/Plugins/Podio/PodioDynamicColumns.hpp" #include "Acts/Plugins/Podio/PodioUtil.hpp" +#include "ActsPodioEdm/Surface.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wold-style-cast" @@ -207,9 +208,15 @@ class MutablePodioTrackContainer : public PodioTrackContainerBase { void setReferenceSurface_impl(IndexType itrack, std::shared_ptr surface) { auto track = m_collection->at(itrack); - track.setReferenceSurface( - PodioUtil::convertSurfaceToPodio(m_helper, *surface)); - m_surfaces.at(itrack) = std::move(surface); + if (surface == nullptr) { + track.setReferenceSurface({.surfaceType = PodioUtil::kNoSurface, + .identifier = PodioUtil::kNoIdentifier}); + m_surfaces.at(itrack) = nullptr; + } else { + track.setReferenceSurface( + PodioUtil::convertSurfaceToPodio(m_helper, *surface)); + m_surfaces.at(itrack) = std::move(surface); + } } public: diff --git a/Tests/CommonHelpers/Acts/Tests/CommonHelpers/CylindricalDetector.cpp b/Tests/CommonHelpers/Acts/Tests/CommonHelpers/CylindricalDetector.cpp new file mode 100644 index 00000000000..d5aec8bf735 --- /dev/null +++ b/Tests/CommonHelpers/Acts/Tests/CommonHelpers/CylindricalDetector.cpp @@ -0,0 +1,115 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 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 http://mozilla.org/MPL/2.0/. + +#include "Acts/Tests/CommonHelpers/CylindricalDetector.hpp" + +#include "Acts/Detector/CylindricalContainerBuilder.hpp" +#include "Acts/Detector/DetectorBuilder.hpp" +#include "Acts/Detector/DetectorComponents.hpp" +#include "Acts/Detector/DetectorVolume.hpp" +#include "Acts/Detector/GeometryIdGenerator.hpp" +#include "Acts/Geometry/CylinderVolumeBounds.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Material/BinnedSurfaceMaterial.hpp" +#include "Acts/Material/HomogeneousSurfaceMaterial.hpp" +#include "Acts/Material/Material.hpp" +#include "Acts/Material/MaterialSlab.hpp" +#include "Acts/Navigation/DetectorVolumeFinders.hpp" +#include "Acts/Navigation/InternalNavigation.hpp" +#include "Acts/Surfaces/CylinderBounds.hpp" +#include "Acts/Surfaces/CylinderSurface.hpp" +#include "Acts/Surfaces/DiscSurface.hpp" +#include "Acts/Surfaces/RadialBounds.hpp" + +#include + +auto materialSlab = + Acts::MaterialSlab(Acts::Material::fromMolarDensity(1, 2, 3, 4, 5), 1.); + +using namespace Acts; +using namespace Acts::Experimental; + +std::shared_ptr Acts::Test::buildCylindricalDetector( + const Acts::GeometryContext& tContext) { + auto material = + std::make_shared(materialSlab); + + auto beampipe = std::make_shared< + CylindricalVolumeBuilder>( + Transform3::Identity(), CylinderVolumeBounds(0., 50., 400.), + CylinderBounds(25., 380.), "BeamPipe", material); + + // Declare a negative disc builder + Transform3 negZ = Transform3::Identity(); + negZ.pretranslate(Vector3(0., 0., -300.)); + auto endcapN = + std::make_shared>( + negZ, CylinderVolumeBounds(50., 140., 100.), RadialBounds(60., 120.), + "NegativeEndcap", material); + + // Declare a barrel sub builder + auto barrel0 = std::make_shared< + CylindricalVolumeBuilder>( + Transform3::Identity(), CylinderVolumeBounds(50., 80., 200.), + CylinderBounds(65., 180.), "Barrel0", material); + + // Declare a barrel sub builder + auto barrel1 = std::make_shared< + CylindricalVolumeBuilder>( + Transform3::Identity(), CylinderVolumeBounds(80., 110., 200.), + CylinderBounds(95., 180.), "Barrel1", material); + + // Declare a barrel sub builder + auto barrel2 = std::make_shared< + CylindricalVolumeBuilder>( + Transform3::Identity(), CylinderVolumeBounds(110., 140., 200.), + CylinderBounds(125., 180.), "Barrel2", material); + + // Create the barrel container builder + CylindricalContainerBuilder::Config barrelRCfg; + barrelRCfg.builders = {barrel0, barrel1, barrel2}; + barrelRCfg.binning = {BinningValue::binR}; + + auto barrel = std::make_shared( + barrelRCfg, getDefaultLogger("BarrelBuilderR", Logging::INFO)); + + Transform3 posZ = Transform3::Identity(); + posZ.pretranslate(Vector3(0., 0., 300.)); + auto endcapP = + std::make_shared>( + posZ, CylinderVolumeBounds(50., 140., 100.), RadialBounds(60., 120.), + "PositiveEndcap", material); + + // Create the barrel container builder + CylindricalContainerBuilder::Config barrelEndcapCfg; + barrelEndcapCfg.builders = {endcapN, barrel, endcapP}; + barrelEndcapCfg.binning = {BinningValue::binZ}; + + auto barrelEndcap = std::make_shared( + barrelEndcapCfg, getDefaultLogger("BarrelEndcapBuilder", Logging::INFO)); + + // Create the barrel container builder + CylindricalContainerBuilder::Config detectorCfg; + detectorCfg.builders = {beampipe, barrelEndcap}; + detectorCfg.binning = {BinningValue::binR}; + + auto containerBuilder = std::make_shared( + detectorCfg, getDefaultLogger("DetectorBuilder", Logging::INFO)); + + // Detector builder + auto gigConfig = GeometryIdGenerator::Config(); + auto gig = std::make_shared(gigConfig); + + Acts::Experimental::DetectorBuilder::Config dCfg; + dCfg.auxiliary = "*** Test : Cylindrical Detector ***"; + dCfg.name = "CylindricalDetector"; + dCfg.builder = containerBuilder; + dCfg.geoIdGenerator = gig; + + return DetectorBuilder(dCfg).construct(tContext); +} diff --git a/Tests/CommonHelpers/Acts/Tests/CommonHelpers/CylindricalDetector.hpp b/Tests/CommonHelpers/Acts/Tests/CommonHelpers/CylindricalDetector.hpp new file mode 100644 index 00000000000..b8b5e4df21d --- /dev/null +++ b/Tests/CommonHelpers/Acts/Tests/CommonHelpers/CylindricalDetector.hpp @@ -0,0 +1,91 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 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 http://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Definitions/Algebra.hpp" +#include "Acts/Detector/DetectorComponents.hpp" +#include "Acts/Detector/DetectorVolume.hpp" +#include "Acts/Detector/PortalGenerators.hpp" +#include "Acts/Detector/interface/IDetectorComponentBuilder.hpp" +#include "Acts/Geometry/CylinderVolumeBounds.hpp" +#include "Acts/Navigation/DetectorVolumeFinders.hpp" +#include "Acts/Navigation/InternalNavigation.hpp" + +#include +#include + +namespace Acts { + +class ISurfaceMaterial; + +using namespace Experimental; + +namespace Test { + +/// @brief A mockup volume builder, it generates volumes with +/// a single surface filled in in order to use the CylindricalContainerBuilder +/// infrastructure. +template +class CylindricalVolumeBuilder : public IDetectorComponentBuilder { + public: + CylindricalVolumeBuilder( + const Transform3& transform, const CylinderVolumeBounds& vBounds, + const surface_bounds_type& sBounds, const std::string& vName, + std::shared_ptr material = nullptr) + : IDetectorComponentBuilder(), + m_transform(transform), + m_volumeBounds(vBounds), + m_surfaceBounds(sBounds), + m_name(vName), + m_material(std::move(material)) {} + + DetectorComponent construct( + [[maybe_unused]] const GeometryContext& gctx) const final { + // The outgoing root volumes + std::vector> rootVolumes; + + // Ingredients + auto surface = Surface::makeShared( + (m_transform), std::make_shared(m_surfaceBounds)); + surface->assignSurfaceMaterial(m_material); + + auto bounds = std::make_unique(m_volumeBounds); + auto portalGenerator = defaultPortalGenerator(); + auto volume = DetectorVolumeFactory::construct( + portalGenerator, gctx, m_name, m_transform, std::move(bounds), + {surface}, {}, tryNoVolumes(), tryAllPortalsAndSurfaces()); + + // Add to the roots + rootVolumes.push_back(volume); + + DetectorComponent::PortalContainer dContainer; + for (auto [ip, p] : enumerate(volume->portalPtrs())) { + dContainer[ip] = p; + } + return DetectorComponent{ + {volume}, + dContainer, + RootDetectorVolumes{rootVolumes, tryRootVolumes()}}; + } + + private: + Transform3 m_transform; + CylinderVolumeBounds m_volumeBounds; + surface_bounds_type m_surfaceBounds; + std::string m_name; + std::shared_ptr m_material = nullptr; +}; + +/// @brief A mockup container builder, it generates a container with +/// serval cylindrical volumes in it. +std::shared_ptr buildCylindricalDetector( + const GeometryContext& tContext); + +} // namespace Test +} // namespace Acts diff --git a/Tests/CommonHelpers/CMakeLists.txt b/Tests/CommonHelpers/CMakeLists.txt index 12d42d851ab..84417f3ddb4 100644 --- a/Tests/CommonHelpers/CMakeLists.txt +++ b/Tests/CommonHelpers/CMakeLists.txt @@ -5,6 +5,7 @@ add_library( ActsTestsCommonHelpers SHARED Acts/Tests/CommonHelpers/DataDirectory.cpp + Acts/Tests/CommonHelpers/CylindricalDetector.cpp ) target_compile_definitions( ActsTestsCommonHelpers diff --git a/Tests/UnitTests/Core/Detector/CylindricalContainerBuilderTests.cpp b/Tests/UnitTests/Core/Detector/CylindricalContainerBuilderTests.cpp index 5fe880f57dd..fa15d5eb076 100644 --- a/Tests/UnitTests/Core/Detector/CylindricalContainerBuilderTests.cpp +++ b/Tests/UnitTests/Core/Detector/CylindricalContainerBuilderTests.cpp @@ -26,6 +26,7 @@ #include "Acts/Surfaces/DiscSurface.hpp" #include "Acts/Surfaces/RadialBounds.hpp" #include "Acts/Surfaces/Surface.hpp" +#include "Acts/Tests/CommonHelpers/CylindricalDetector.hpp" #include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/Enumerate.hpp" #include "Acts/Utilities/Logger.hpp" @@ -40,61 +41,11 @@ #include using namespace Acts; +using namespace Acts::Test; using namespace Acts::Experimental; GeometryContext tContext; -/// @brief A mockup volume builder, it generates volumes with -/// a single surface filled in in order to use the CylindricalContainerBuilder -/// infrastructure. -template -class CylindricalVolumeBuilder : public IDetectorComponentBuilder { - public: - CylindricalVolumeBuilder(const Transform3& transform, - const CylinderVolumeBounds& vBounds, - const surface_bounds_type& sBounds, - const std::string& vName) - : IDetectorComponentBuilder(), - m_transform(transform), - m_volumeBounds(vBounds), - m_surfaceBounds(sBounds), - m_name(vName) {} - - DetectorComponent construct( - [[maybe_unused]] const GeometryContext& gctx) const final { - // The outgoing root volumes - std::vector> rootVolumes; - - // Ingredients - auto surface = Surface::makeShared( - (m_transform), std::make_shared(m_surfaceBounds)); - - auto bounds = std::make_unique(m_volumeBounds); - auto portalGenerator = defaultPortalGenerator(); - auto volume = DetectorVolumeFactory::construct( - portalGenerator, tContext, m_name, m_transform, std::move(bounds), - {surface}, {}, tryNoVolumes(), tryAllPortalsAndSurfaces()); - - // Add to the roots - rootVolumes.push_back(volume); - - DetectorComponent::PortalContainer dContainer; - for (auto [ip, p] : enumerate(volume->portalPtrs())) { - dContainer[ip] = p; - } - return DetectorComponent{ - {volume}, - dContainer, - RootDetectorVolumes{rootVolumes, tryRootVolumes()}}; - } - - private: - Transform3 m_transform; - CylinderVolumeBounds m_volumeBounds; - surface_bounds_type m_surfaceBounds; - std::string m_name; -}; - class VolumeGeoIdGenerator : public IGeometryIdGenerator { public: struct Cache { diff --git a/Tests/UnitTests/Core/TrackFinding/TrackSelectorTests.cpp b/Tests/UnitTests/Core/TrackFinding/TrackSelectorTests.cpp index 7c7a265d4d4..dfdf33885ed 100644 --- a/Tests/UnitTests/Core/TrackFinding/TrackSelectorTests.cpp +++ b/Tests/UnitTests/Core/TrackFinding/TrackSelectorTests.cpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2023 CERN for the benefit of the Acts project +// Copyright (C) 2023-2024 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 @@ -25,6 +25,11 @@ using namespace Acts; namespace bdata = boost::unit_test::data; struct MockTrack { + static constexpr bool ReadOnly = true; + using Container = VectorTrackContainer; + using Trajectory = VectorMultiTrajectory; + using IndexType = TrackIndexType; + double m_theta; double m_phi; double m_pt; diff --git a/Tests/UnitTests/Examples/EventData/MeasurementTests.cpp b/Tests/UnitTests/Examples/EventData/MeasurementTests.cpp index bab0b16e9e9..0156e01f03e 100644 --- a/Tests/UnitTests/Examples/EventData/MeasurementTests.cpp +++ b/Tests/UnitTests/Examples/EventData/MeasurementTests.cpp @@ -50,16 +50,19 @@ std::default_random_engine rng(123); BOOST_AUTO_TEST_SUITE(EventDataMeasurement) BOOST_DATA_TEST_CASE(VariableBoundOne, bd::make(boundIndices), index) { + MeasurementContainer container; + auto [params, cov] = generateParametersCovariance(rng); - auto meas = makeVariableSizeMeasurement(source, params, cov, index); + + FixedBoundMeasurementProxy<1> meas = container.makeMeasurement<1>(); + meas.setSourceLink(source); + meas.setSubspaceIndices(std::array{index}); + meas.parameters() = params; + meas.covariance() = cov; BOOST_CHECK_EQUAL(meas.size(), 1); for (auto i : boundIndices) { - if (i == index) { - BOOST_CHECK(meas.contains(i)); - } else { - BOOST_CHECK(!meas.contains(i)); - } + BOOST_CHECK_EQUAL(meas.contains(i), i == index); } BOOST_CHECK_EQUAL(meas.parameters(), params); BOOST_CHECK_EQUAL(meas.covariance(), cov); @@ -68,10 +71,17 @@ BOOST_DATA_TEST_CASE(VariableBoundOne, bd::make(boundIndices), index) { } BOOST_AUTO_TEST_CASE(VariableBoundAll) { + MeasurementContainer container; + auto [params, cov] = generateBoundParametersCovariance(rng); - auto meas = makeVariableSizeMeasurement(source, params, cov, eBoundLoc0, - eBoundLoc1, eBoundPhi, eBoundTheta, - eBoundQOverP, eBoundTime); + + FixedBoundMeasurementProxy meas = + container.makeMeasurement(); + meas.setSourceLink(source); + meas.setSubspaceIndices(std::array{eBoundLoc0, eBoundLoc1, eBoundTime, + eBoundPhi, eBoundTheta, eBoundQOverP}); + meas.parameters() = params; + meas.covariance() = cov; BOOST_CHECK_EQUAL(meas.size(), eBoundSize); for (auto i : boundIndices) { @@ -83,22 +93,35 @@ BOOST_AUTO_TEST_CASE(VariableBoundAll) { } BOOST_AUTO_TEST_CASE(VariableBoundReassign) { - // generate w/ a single parameter - auto [par1, cov1] = generateParametersCovariance(rng); - auto meas = makeVariableSizeMeasurement(source, par1, cov1, eBoundTheta); - BOOST_CHECK_EQUAL(meas.size(), 1); + MeasurementContainer container; + + // generate w/ two parameter + auto [params1, cov1] = generateParametersCovariance(rng); + + VariableBoundMeasurementProxy meas = container.makeMeasurement(2); + meas.setSourceLink(source); + meas.setSubspaceIndices(std::array{eBoundPhi, eBoundTheta}); + meas.parameters() = params1; + meas.covariance() = cov1; + + BOOST_CHECK_EQUAL(meas.size(), 2); BOOST_CHECK(!meas.contains(eBoundLoc0)); BOOST_CHECK(!meas.contains(eBoundLoc1)); BOOST_CHECK(!meas.contains(eBoundTime)); - BOOST_CHECK(!meas.contains(eBoundPhi)); + BOOST_CHECK(meas.contains(eBoundPhi)); BOOST_CHECK(meas.contains(eBoundTheta)); BOOST_CHECK(!meas.contains(eBoundQOverP)); // reassign w/ all parameters - auto [parN, covN] = generateBoundParametersCovariance(rng); - meas = makeVariableSizeMeasurement(source, parN, covN, eBoundLoc0, eBoundLoc1, - eBoundPhi, eBoundTheta, eBoundQOverP, - eBoundTime); + auto [paramsN, covN] = generateBoundParametersCovariance(rng); + + meas = container.makeMeasurement(eBoundSize); + meas.setSourceLink(source); + meas.setSubspaceIndices(std::array{eBoundLoc0, eBoundLoc1, eBoundTime, + eBoundPhi, eBoundTheta, eBoundQOverP}); + meas.parameters() = paramsN; + meas.covariance() = covN; + BOOST_CHECK_EQUAL(meas.size(), eBoundSize); BOOST_CHECK(meas.contains(eBoundLoc0)); BOOST_CHECK(meas.contains(eBoundLoc1)); diff --git a/Tests/UnitTests/Examples/Io/Csv/MeasurementReaderWriterTests.cpp b/Tests/UnitTests/Examples/Io/Csv/MeasurementReaderWriterTests.cpp index 4b4b6d78bbe..7fa64dcb128 100644 --- a/Tests/UnitTests/Examples/Io/Csv/MeasurementReaderWriterTests.cpp +++ b/Tests/UnitTests/Examples/Io/Csv/MeasurementReaderWriterTests.cpp @@ -50,11 +50,11 @@ BOOST_AUTO_TEST_CASE(CsvMeasurementRoundTrip) { Acts::Vector2 p = Acts::Vector2::Random(); Acts::SquareMatrix2 c = Acts::SquareMatrix2::Random(); - BoundVariableMeasurement m(Acts::SourceLink{sl}, - std::array{Acts::eBoundLoc0, Acts::eBoundLoc1}, - p, c); - - measOriginal.push_back(m); + FixedBoundMeasurementProxy<2> m = measOriginal.makeMeasurement<2>(); + m.setSourceLink(Acts::SourceLink(sl)); + m.setSubspaceIndices(std::array{Acts::eBoundLoc0, Acts::eBoundLoc1}); + m.parameters() = p; + m.covariance() = c; ActsExamples::Cluster cl; diff --git a/Tests/UnitTests/Plugins/ActSVG/DetectorSvgConverterTests.cpp b/Tests/UnitTests/Plugins/ActSVG/DetectorSvgConverterTests.cpp index cb28a9766ff..b4080848402 100644 --- a/Tests/UnitTests/Plugins/ActSVG/DetectorSvgConverterTests.cpp +++ b/Tests/UnitTests/Plugins/ActSVG/DetectorSvgConverterTests.cpp @@ -27,6 +27,7 @@ #include "Acts/Surfaces/DiscSurface.hpp" #include "Acts/Surfaces/RadialBounds.hpp" #include "Acts/Surfaces/Surface.hpp" +#include "Acts/Tests/CommonHelpers/CylindricalDetector.hpp" #include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/Enumerate.hpp" #include "Acts/Utilities/Logger.hpp" @@ -36,139 +37,15 @@ #include using namespace Acts; +using namespace Acts::Test; using namespace Acts::Experimental; GeometryContext tContext; -/// @brief A mockup volume builder, it generates volumes with -/// a single surface filled in in order to use the CylindricalContainerBuilder -/// infrastructure. -template -class CylindricalVolumeBuilder : public IDetectorComponentBuilder { - public: - CylindricalVolumeBuilder(const Transform3& transform, - const CylinderVolumeBounds& vBounds, - const surface_bounds_type& sBounds, - const std::string& vName) - : IDetectorComponentBuilder(), - m_transform(transform), - m_volumeBounds(vBounds), - m_surfaceBounds(sBounds), - m_name(vName) {} - - DetectorComponent construct( - [[maybe_unused]] const GeometryContext& gctx) const final { - // The outgoing root volumes - std::vector> rootVolumes; - - // Ingredients - auto surface = Surface::makeShared( - (m_transform), std::make_shared(m_surfaceBounds)); - - auto bounds = std::make_unique(m_volumeBounds); - auto portalGenerator = defaultPortalGenerator(); - auto volume = DetectorVolumeFactory::construct( - portalGenerator, tContext, m_name, m_transform, std::move(bounds), - {surface}, {}, tryNoVolumes(), tryAllPortalsAndSurfaces()); - - // Add to the roots - rootVolumes.push_back(volume); - - DetectorComponent::PortalContainer dContainer; - for (auto [ip, p] : enumerate(volume->portalPtrs())) { - dContainer[ip] = p; - } - return DetectorComponent{ - {volume}, - dContainer, - RootDetectorVolumes{rootVolumes, tryRootVolumes()}}; - } - - private: - Transform3 m_transform; - CylinderVolumeBounds m_volumeBounds; - surface_bounds_type m_surfaceBounds; - std::string m_name; -}; - BOOST_AUTO_TEST_SUITE(ActSvg) BOOST_AUTO_TEST_CASE(CylindricalDetector) { - // Declare a barrel sub builder - auto beampipe = std::make_shared< - CylindricalVolumeBuilder>( - Transform3::Identity(), CylinderVolumeBounds(0., 50., 400.), - CylinderBounds(25., 380.), "BeamPipe"); - - // Declare a negative disc builder - Transform3 negZ = Transform3::Identity(); - negZ.pretranslate(Vector3(0., 0., -300.)); - auto endcapN = - std::make_shared>( - negZ, CylinderVolumeBounds(50., 140., 100.), RadialBounds(60., 120.), - "NegativeEndcap"); - - // Declare a barrel sub builder - auto barrel0 = std::make_shared< - CylindricalVolumeBuilder>( - Transform3::Identity(), CylinderVolumeBounds(50., 80., 200.), - CylinderBounds(65., 180.), "Barrel0"); - - // Declare a barrel sub builder - auto barrel1 = std::make_shared< - CylindricalVolumeBuilder>( - Transform3::Identity(), CylinderVolumeBounds(80., 110., 200.), - CylinderBounds(95., 180.), "Barrel1"); - - // Declare a barrel sub builder - auto barrel2 = std::make_shared< - CylindricalVolumeBuilder>( - Transform3::Identity(), CylinderVolumeBounds(110., 140., 200.), - CylinderBounds(125., 180.), "Barrel2"); - - // Create the barrel container builder - CylindricalContainerBuilder::Config barrelRCfg; - barrelRCfg.builders = {barrel0, barrel1, barrel2}; - barrelRCfg.binning = {BinningValue::binR}; - - auto barrel = std::make_shared( - barrelRCfg, getDefaultLogger("BarrelBuilderR", Logging::VERBOSE)); - - Transform3 posZ = Transform3::Identity(); - posZ.pretranslate(Vector3(0., 0., 300.)); - auto endcapP = - std::make_shared>( - posZ, CylinderVolumeBounds(50., 140., 100.), RadialBounds(60., 120.), - "PositiveEndcap"); - - // Create the barrel container builder - CylindricalContainerBuilder::Config barrelEndcapCfg; - barrelEndcapCfg.builders = {endcapN, barrel, endcapP}; - barrelEndcapCfg.binning = {BinningValue::binZ}; - - auto barrelEndcap = std::make_shared( - barrelEndcapCfg, - getDefaultLogger("BarrelEndcapBuilder", Logging::VERBOSE)); - - // Create the barrel container builder - CylindricalContainerBuilder::Config detectorCfg; - detectorCfg.builders = {beampipe, barrelEndcap}; - detectorCfg.binning = {BinningValue::binR}; - - auto containerBuilder = std::make_shared( - detectorCfg, getDefaultLogger("DetectorBuilder", Logging::VERBOSE)); - - // Detector builder - auto gigConfig = GeometryIdGenerator::Config(); - auto gig = std::make_shared(gigConfig); - - Acts::Experimental::DetectorBuilder::Config dCfg; - dCfg.auxiliary = "*** Test : Cylindrical Detector ***"; - dCfg.name = "CylindricalDetector"; - dCfg.builder = containerBuilder; - dCfg.geoIdGenerator = gig; - - auto detector = DetectorBuilder(dCfg).construct(tContext); + auto detector = buildCylindricalDetector(tContext); Acts::Svg::DetectorConverter::Options detectorOptions; auto pDetector = Acts::Svg::DetectorConverter::convert(tContext, *detector, diff --git a/Tests/UnitTests/Plugins/Detray/CMakeLists.txt b/Tests/UnitTests/Plugins/Detray/CMakeLists.txt index ea326ba2ecb..f621fa1261d 100644 --- a/Tests/UnitTests/Plugins/Detray/CMakeLists.txt +++ b/Tests/UnitTests/Plugins/Detray/CMakeLists.txt @@ -1,3 +1,4 @@ set(unittest_extra_libraries ActsPluginDetray) +add_unittest(DetrayConverter DetrayConverterTests.cpp) add_unittest(DetrayGeometryConverter DetrayGeometryConverterTests.cpp) add_unittest(DetrayMaterialConverter DetrayMaterialConverterTests.cpp) diff --git a/Tests/UnitTests/Plugins/Detray/DetrayConverterTests.cpp b/Tests/UnitTests/Plugins/Detray/DetrayConverterTests.cpp new file mode 100644 index 00000000000..2e6377f2cdc --- /dev/null +++ b/Tests/UnitTests/Plugins/Detray/DetrayConverterTests.cpp @@ -0,0 +1,51 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 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 http://mozilla.org/MPL/2.0/. + +#include + +#include "Acts/Plugins/Detray/DetrayConverter.hpp" +#include "Acts/Tests/CommonHelpers/CylindricalDetector.hpp" + +#include +#include + +using namespace Acts; +using namespace Acts::Experimental; +using namespace Acts::Test; + +GeometryContext tContext; + +auto logger = + Acts::getDefaultLogger("DetrayConverterTests", Acts::Logging::INFO); + +BOOST_AUTO_TEST_SUITE(DetrayConversion) + +BOOST_AUTO_TEST_CASE(DetrayConversion) { + // Load the detector from the Test utilities + auto detector = buildCylindricalDetector(tContext); + + DetrayConverter::Options options; + + vecmem::host_memory_resource memoryResource; + + auto detrayDetector = + DetrayConverter(std::move(logger)) + .convert<>(tContext, *detector, memoryResource, options); + + BOOST_CHECK_EQUAL(detrayDetector.volumes().size(), 6u); + // Beampipe : original 3 -> split into 5 + // Nec: original 4 -> split into 6 + // Layer0: original 4 -> left at 4 + // Layer1: original 4 -> left at 4 + // Layer2: original 4 -> left at 4 + // Pec: original 4 -> split into 6 + // + portals to itself, one per volume 6 + BOOST_CHECK_EQUAL(detrayDetector.portals().size(), 35u); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/Tests/UnitTests/Plugins/Detray/DetrayGeometryConverterTests.cpp b/Tests/UnitTests/Plugins/Detray/DetrayGeometryConverterTests.cpp index c37ff7bf96f..41e283ccc49 100644 --- a/Tests/UnitTests/Plugins/Detray/DetrayGeometryConverterTests.cpp +++ b/Tests/UnitTests/Plugins/Detray/DetrayGeometryConverterTests.cpp @@ -9,24 +9,14 @@ #include #include "Acts/Definitions/Algebra.hpp" -#include "Acts/Detector/CylindricalContainerBuilder.hpp" -#include "Acts/Detector/Detector.hpp" -#include "Acts/Detector/DetectorBuilder.hpp" -#include "Acts/Detector/DetectorComponents.hpp" #include "Acts/Detector/DetectorVolume.hpp" -#include "Acts/Detector/GeometryIdGenerator.hpp" -#include "Acts/Detector/PortalGenerators.hpp" -#include "Acts/Detector/interface/IDetectorComponentBuilder.hpp" #include "Acts/Geometry/CylinderVolumeBounds.hpp" #include "Acts/Geometry/GeometryContext.hpp" -#include "Acts/Navigation/DetectorVolumeFinders.hpp" -#include "Acts/Navigation/InternalNavigation.hpp" #include "Acts/Plugins/Detray/DetrayGeometryConverter.hpp" #include "Acts/Surfaces/CylinderBounds.hpp" #include "Acts/Surfaces/CylinderSurface.hpp" -#include "Acts/Surfaces/DiscSurface.hpp" -#include "Acts/Surfaces/RadialBounds.hpp" #include "Acts/Surfaces/Surface.hpp" +#include "Acts/Tests/CommonHelpers/CylindricalDetector.hpp" #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" #include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/Enumerate.hpp" @@ -39,63 +29,13 @@ using namespace Acts; using namespace Acts::Experimental; +using namespace Acts::Test; GeometryContext tContext; auto logger = Acts::getDefaultLogger("DetrayGeometryConverterTests", Acts::Logging::INFO); -/// @brief A mockup volume builder, it generates volumes with -/// a single surface filled in in order to use the CylindricalContainerBuilder -/// infrastructure. -template -class CylindricalVolumeBuilder : public IDetectorComponentBuilder { - public: - CylindricalVolumeBuilder(const Transform3& transform, - const CylinderVolumeBounds& vBounds, - const surface_bounds_type& sBounds, - const std::string& vName) - : IDetectorComponentBuilder(), - m_transform(transform), - m_volumeBounds(vBounds), - m_surfaceBounds(sBounds), - m_name(vName) {} - - DetectorComponent construct( - [[maybe_unused]] const GeometryContext& gctx) const final { - // The outgoing root volumes - std::vector> rootVolumes; - - // Ingredients - auto surface = Surface::makeShared( - (m_transform), std::make_shared(m_surfaceBounds)); - - auto bounds = std::make_unique(m_volumeBounds); - auto portalGenerator = defaultPortalGenerator(); - auto volume = DetectorVolumeFactory::construct( - portalGenerator, tContext, m_name, m_transform, std::move(bounds), - {surface}, {}, tryNoVolumes(), tryAllPortalsAndSurfaces()); - - // Add to the roots - rootVolumes.push_back(volume); - - DetectorComponent::PortalContainer dContainer; - for (auto [ip, p] : enumerate(volume->portalPtrs())) { - dContainer[ip] = p; - } - return DetectorComponent{ - {volume}, - dContainer, - RootDetectorVolumes{rootVolumes, tryRootVolumes()}}; - } - - private: - Transform3 m_transform; - CylinderVolumeBounds m_volumeBounds; - surface_bounds_type m_surfaceBounds; - std::string m_name; -}; - BOOST_AUTO_TEST_SUITE(DetrayConversion) BOOST_AUTO_TEST_CASE(DetrayTransformConversion) { @@ -113,7 +53,7 @@ BOOST_AUTO_TEST_CASE(DetrayTransformConversion) { CHECK_CLOSE_ABS(payload.tr[2u], 3., std::numeric_limits::epsilon()); // Rotation is correctly translated - const auto rotation = transform.rotation(); + RotationMatrix3 rotation = transform.rotation().transpose(); CHECK_CLOSE_ABS(payload.rot[0u], rotation(0, 0), std::numeric_limits::epsilon()); CHECK_CLOSE_ABS(payload.rot[1u], rotation(0, 1), @@ -190,80 +130,8 @@ BOOST_AUTO_TEST_CASE(DetrayVolumeConversion) { } BOOST_AUTO_TEST_CASE(CylindricalDetector) { - // Declare a barrel sub builder - auto beampipe = std::make_shared< - CylindricalVolumeBuilder>( - Transform3::Identity(), CylinderVolumeBounds(0., 50., 400.), - CylinderBounds(25., 380.), "BeamPipe"); - - // Declare a negative disc builder - Transform3 negZ = Transform3::Identity(); - negZ.pretranslate(Vector3(0., 0., -300.)); - auto endcapN = - std::make_shared>( - negZ, CylinderVolumeBounds(50., 140., 100.), RadialBounds(60., 120.), - "NegativeEndcap"); - - // Declare a barrel sub builder - auto barrel0 = std::make_shared< - CylindricalVolumeBuilder>( - Transform3::Identity(), CylinderVolumeBounds(50., 80., 200.), - CylinderBounds(65., 180.), "Barrel0"); - - // Declare a barrel sub builder - auto barrel1 = std::make_shared< - CylindricalVolumeBuilder>( - Transform3::Identity(), CylinderVolumeBounds(80., 110., 200.), - CylinderBounds(95., 180.), "Barrel1"); - - // Declare a barrel sub builder - auto barrel2 = std::make_shared< - CylindricalVolumeBuilder>( - Transform3::Identity(), CylinderVolumeBounds(110., 140., 200.), - CylinderBounds(125., 180.), "Barrel2"); - - // Create the barrel container builder - CylindricalContainerBuilder::Config barrelRCfg; - barrelRCfg.builders = {barrel0, barrel1, barrel2}; - barrelRCfg.binning = {BinningValue::binR}; - - auto barrel = std::make_shared( - barrelRCfg, getDefaultLogger("BarrelBuilderR", Logging::INFO)); - - Transform3 posZ = Transform3::Identity(); - posZ.pretranslate(Vector3(0., 0., 300.)); - auto endcapP = - std::make_shared>( - posZ, CylinderVolumeBounds(50., 140., 100.), RadialBounds(60., 120.), - "PositiveEndcap"); - - // Create the barrel container builder - CylindricalContainerBuilder::Config barrelEndcapCfg; - barrelEndcapCfg.builders = {endcapN, barrel, endcapP}; - barrelEndcapCfg.binning = {BinningValue::binZ}; - - auto barrelEndcap = std::make_shared( - barrelEndcapCfg, getDefaultLogger("BarrelEndcapBuilder", Logging::INFO)); - - // Create the barrel container builder - CylindricalContainerBuilder::Config detectorCfg; - detectorCfg.builders = {beampipe, barrelEndcap}; - detectorCfg.binning = {BinningValue::binR}; - - auto containerBuilder = std::make_shared( - detectorCfg, getDefaultLogger("DetectorBuilder", Logging::INFO)); - - // Detector builder - auto gigConfig = GeometryIdGenerator::Config(); - auto gig = std::make_shared(gigConfig); - - Acts::Experimental::DetectorBuilder::Config dCfg; - dCfg.auxiliary = "*** Test : Cylindrical Detector ***"; - dCfg.name = "CylindricalDetector"; - dCfg.builder = containerBuilder; - dCfg.geoIdGenerator = gig; - - auto detector = DetectorBuilder(dCfg).construct(tContext); + // Load the detector from the Test utilities + auto detector = buildCylindricalDetector(tContext); // Convert the detector DetrayConversionUtils::GeometryIdCache geoIdCache; diff --git a/Tests/UnitTests/Plugins/Detray/DetrayMaterialConverterTests.cpp b/Tests/UnitTests/Plugins/Detray/DetrayMaterialConverterTests.cpp index 0d5aa41bcc8..702d7a25001 100644 --- a/Tests/UnitTests/Plugins/Detray/DetrayMaterialConverterTests.cpp +++ b/Tests/UnitTests/Plugins/Detray/DetrayMaterialConverterTests.cpp @@ -8,12 +8,14 @@ #include +#include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Material/BinnedSurfaceMaterial.hpp" #include "Acts/Material/HomogeneousSurfaceMaterial.hpp" #include "Acts/Material/Material.hpp" #include "Acts/Material/MaterialSlab.hpp" #include "Acts/Plugins/Detray/DetrayConversionUtils.hpp" #include "Acts/Plugins/Detray/DetrayMaterialConverter.hpp" +#include "Acts/Tests/CommonHelpers/CylindricalDetector.hpp" #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" #include "Acts/Utilities/BinUtility.hpp" #include "Acts/Utilities/Logger.hpp" @@ -21,6 +23,8 @@ #include #include +auto tContext = Acts::GeometryContext(); + BOOST_AUTO_TEST_SUITE(DetrayConversion) // These tests check the conversion to the payload objects, the full test @@ -69,6 +73,20 @@ BOOST_AUTO_TEST_CASE(DetrayMaterialSlabConversion) { std::numeric_limits::epsilon()); } +BOOST_AUTO_TEST_CASE(DetrayHomogeneousMaterialConversion) { + // Convert homogeneous material + Acts::HomogeneousSurfaceMaterial homMaterial(materialSlab12345); + + detray::io::grid_payload + payload = Acts::DetrayMaterialConverter::convertGridSurfaceMaterial( + homMaterial, *logger); + + // Check the payload - empty, this should run through another converter + BOOST_CHECK(payload.axes.empty()); + BOOST_CHECK(payload.bins.empty()); +} + BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionX) { // Create a binned material in 4 bins in x direction Acts::BinUtility binUtility(4u, -2., 2., Acts::BinningOption::open, @@ -83,7 +101,7 @@ BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionX) { detray::io::grid_payload - payload = Acts::DetrayMaterialConverter::convertSurfaceMaterial( + payload = Acts::DetrayMaterialConverter::convertGridSurfaceMaterial( binnedMaterial, *logger); // Check the payload // - we fake 2D always for detray to minimize the number of containers @@ -143,7 +161,7 @@ BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionY) { detray::io::grid_payload - payload = Acts::DetrayMaterialConverter::convertSurfaceMaterial( + payload = Acts::DetrayMaterialConverter::convertGridSurfaceMaterial( binnedMaterial, *logger); // Check the payload // - we fake 2D always for detray to minimize the number of containers @@ -207,7 +225,7 @@ BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionXY) { detray::io::grid_payload - payload = Acts::DetrayMaterialConverter::convertSurfaceMaterial( + payload = Acts::DetrayMaterialConverter::convertGridSurfaceMaterial( binnedMaterial, *logger); // Check the payload BOOST_CHECK_EQUAL(payload.axes.size(), 2u); @@ -260,7 +278,7 @@ BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionR) { detray::io::grid_payload - payload = Acts::DetrayMaterialConverter::convertSurfaceMaterial( + payload = Acts::DetrayMaterialConverter::convertGridSurfaceMaterial( binnedMaterial, *logger); // Check the payload // - we fake 2D always for detray to minimize the number of containers @@ -303,7 +321,7 @@ BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionRPhi) { detray::io::grid_payload - payload = Acts::DetrayMaterialConverter::convertSurfaceMaterial( + payload = Acts::DetrayMaterialConverter::convertGridSurfaceMaterial( binnedMaterial, *logger); // Check the payload BOOST_CHECK_EQUAL(payload.axes.size(), 2u); @@ -337,7 +355,7 @@ BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionZ) { detray::io::grid_payload - payload = Acts::DetrayMaterialConverter::convertSurfaceMaterial( + payload = Acts::DetrayMaterialConverter::convertGridSurfaceMaterial( binnedMaterial, *logger); // Check the payload @@ -380,7 +398,7 @@ BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionZPhi) { detray::io::grid_payload - payload = Acts::DetrayMaterialConverter::convertSurfaceMaterial( + payload = Acts::DetrayMaterialConverter::convertGridSurfaceMaterial( binnedMaterial, *logger); // Check the payload BOOST_CHECK_EQUAL(payload.axes.size(), 2u); @@ -409,7 +427,7 @@ BOOST_AUTO_TEST_CASE(DetrayBinnedMaterialConversionInvalid) { Acts::BinnedSurfaceMaterial(binUtility, {materialSlabs0, materialSlabs1}, 0., Acts::MappingType::Default); - BOOST_CHECK_THROW(Acts::DetrayMaterialConverter::convertSurfaceMaterial( + BOOST_CHECK_THROW(Acts::DetrayMaterialConverter::convertGridSurfaceMaterial( binnedMaterial, *logger), std::invalid_argument); } diff --git a/docs/core/eventdata/tracks.md b/docs/core/eventdata/tracks.md index 4249af5a983..33662b6e397 100644 --- a/docs/core/eventdata/tracks.md +++ b/docs/core/eventdata/tracks.md @@ -442,7 +442,7 @@ std::cout << extraConst(track) << std::endl; // prints 42.2 For both const and mutable proxy accessors you do not actually need a mutable reference, as the internal accessor state is not mutated after construction. You can safely use a static instance of these accessors to avoid constructing them over and over again: ```cpp -template +template void doSomething(track_proxy_t track, float value) { // only created once, never changed static const Acts::ProxyAccessor extra("extra");