Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:10:00

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2019-2020 CERN for the benefit of the Acts project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/Definitions/TrackParametrization.hpp"
0012 #include "Acts/EventData/Measurement.hpp"
0013 #include "Acts/EventData/MeasurementHelpers.hpp"
0014 #include "Acts/EventData/SourceLink.hpp"
0015 #include "Acts/EventData/TrackStatePropMask.hpp"
0016 #include "Acts/EventData/TrackStateProxy.hpp"
0017 #include "Acts/EventData/TrackStateProxyConcept.hpp"
0018 #include "Acts/EventData/TrackStateType.hpp"
0019 #include "Acts/EventData/Types.hpp"
0020 #include "Acts/Geometry/GeometryContext.hpp"
0021 #include "Acts/Utilities/AlgebraHelpers.hpp"
0022 #include "Acts/Utilities/Concepts.hpp"
0023 #include "Acts/Utilities/HashedString.hpp"
0024 #include "Acts/Utilities/Helpers.hpp"
0025 #include "Acts/Utilities/ThrowAssert.hpp"
0026 #include "Acts/Utilities/TypeTraits.hpp"
0027 
0028 #include <bitset>
0029 #include <cstddef>
0030 #include <cstdint>
0031 #include <iterator>
0032 #include <memory>
0033 #include <optional>
0034 #include <type_traits>
0035 #include <vector>
0036 
0037 #include <Eigen/Core>
0038 
0039 namespace Acts {
0040 
0041 // forward declarations
0042 template <typename derived_t>
0043 class MultiTrajectory;
0044 class Surface;
0045 
0046 namespace detail_lt {
0047 
0048 /// Helper type that wraps two iterators
0049 template <bool reverse, typename trajectory_t, std::size_t M, bool ReadOnly>
0050 class TrackStateRange {
0051   using ProxyType = TrackStateProxy<trajectory_t, M, ReadOnly>;
0052   using IndexType = typename ProxyType::IndexType;
0053   static constexpr IndexType kInvalid = ProxyType::kInvalid;
0054 
0055  public:
0056   /// Iterator that wraps a track state proxy. The nullopt case signifies the
0057   /// end of the range, i.e. the "past-the-end" iterator
0058   struct Iterator {
0059     std::optional<ProxyType> proxy;
0060 
0061     using iterator_category = std::forward_iterator_tag;
0062     using value_type = ProxyType;
0063     using difference_type = std::ptrdiff_t;
0064     using pointer = void;
0065     using reference = void;
0066 
0067     Iterator& operator++() {
0068       if (!proxy) {
0069         return *this;
0070       }
0071       if constexpr (reverse) {
0072         if (proxy->hasPrevious()) {
0073           proxy = proxy->trajectory().getTrackState(proxy->previous());
0074           return *this;
0075         } else {
0076           proxy = std::nullopt;
0077           return *this;
0078         }
0079       } else {
0080         IndexType next =
0081             proxy->template component<IndexType, hashString("next")>();
0082         if (next != kInvalid) {
0083           proxy = proxy->trajectory().getTrackState(next);
0084           return *this;
0085         } else {
0086           proxy = std::nullopt;
0087           return *this;
0088         }
0089       }
0090     }
0091 
0092     bool operator==(const Iterator& other) const {
0093       if (!proxy && !other.proxy) {
0094         return true;
0095       }
0096       if (proxy && other.proxy) {
0097         return proxy->index() == other.proxy->index();
0098       }
0099       return false;
0100     }
0101 
0102     bool operator!=(const Iterator& other) const { return !(*this == other); }
0103 
0104     ProxyType operator*() const { return *proxy; }
0105     ProxyType operator*() { return *proxy; }
0106   };
0107 
0108   TrackStateRange(ProxyType _begin) : m_begin{_begin} {}
0109   TrackStateRange() : m_begin{std::nullopt} {}
0110 
0111   Iterator begin() { return m_begin; }
0112   Iterator end() { return Iterator{std::nullopt}; }
0113 
0114  private:
0115   Iterator m_begin;
0116 };
0117 
0118 // implement track state visitor concept
0119 template <typename T, typename TS>
0120 using call_operator_t = decltype(std::declval<T>()(std::declval<TS>()));
0121 
0122 template <typename T, typename TS>
0123 constexpr bool VisitorConcept = Concepts ::require<
0124     Concepts ::either<Concepts ::identical_to<bool, call_operator_t, T, TS>,
0125                       Concepts ::identical_to<void, call_operator_t, T, TS>>>;
0126 
0127 }  // namespace detail_lt
0128 
0129 /// This namespace contains typedefs and constant values that are used by
0130 /// other parts of the @c MultiTrajectory implementation. It extracts these
0131 /// from @c TrackStateTraits using the default maximum measurement dimension.
0132 namespace MultiTrajectoryTraits {
0133 constexpr unsigned int MeasurementSizeMax = eBoundSize;
0134 using IndexType = TrackIndexType;
0135 constexpr IndexType kInvalid = kTrackIndexInvalid;
0136 }  // namespace MultiTrajectoryTraits
0137 
0138 template <typename T>
0139 struct IsReadOnlyMultiTrajectory;
0140 
0141 /// Store a trajectory of track states with multiple components.
0142 ///
0143 /// This container supports both simple, sequential trajectories as well
0144 /// as combinatorial or multi-component trajectories. Each point can store
0145 /// a parent point such that the trajectory forms a directed, acyclic graph
0146 /// of sub-trajectories. From a set of endpoints, all possible sub-components
0147 /// can be easily identified. Some functionality is provided to simplify
0148 /// iterating over specific sub-components.
0149 template <typename derived_t>
0150 class MultiTrajectory {
0151   using Derived = derived_t;
0152 
0153   static constexpr bool ReadOnly = IsReadOnlyMultiTrajectory<Derived>::value;
0154 
0155   // Pull out type alias and re-expose them for ease of use.
0156   static constexpr unsigned int MeasurementSizeMax =
0157       MultiTrajectoryTraits::MeasurementSizeMax;
0158 
0159   friend class TrackStateProxy<Derived, MeasurementSizeMax, true>;
0160   friend class TrackStateProxy<Derived, MeasurementSizeMax, false>;
0161   template <typename T>
0162   friend class MultiTrajectory;
0163 
0164  public:
0165   /// Alias for the const version of a track state proxy, with the same
0166   /// backends as this container
0167   using ConstTrackStateProxy =
0168       Acts::TrackStateProxy<Derived, MeasurementSizeMax, true>;
0169 
0170   /// Alias for the mutable version of a track state proxy, with the same
0171   /// backends as this container
0172   using TrackStateProxy =
0173       Acts::TrackStateProxy<Derived, MeasurementSizeMax, false>;
0174 
0175   /// The index type of the track state container
0176   using IndexType = typename TrackStateProxy::IndexType;
0177 
0178   /// Sentinel value that indicates an invalid index
0179   static constexpr IndexType kInvalid = TrackStateProxy::kInvalid;
0180 
0181  protected:
0182   MultiTrajectory() = default;  // pseudo abstract base class
0183 
0184  private:
0185   /// Helper to static cast this to the Derived class for CRTP
0186   constexpr Derived& self() { return static_cast<Derived&>(*this); }
0187   /// Helper to static cast this to the Derived class for CRTP. Const version.
0188   constexpr const Derived& self() const {
0189     return static_cast<const Derived&>(*this);
0190   }
0191 
0192   /// Helper function to check if a component exists IF it is an optional one.
0193   /// Used in assertions
0194   bool checkOptional(HashedString key, IndexType istate) const {
0195     using namespace Acts::HashedStringLiteral;
0196     switch (key) {
0197       case "predicted"_hash:
0198       case "filtered"_hash:
0199       case "smoothed"_hash:
0200       case "calibrated"_hash:
0201       case "jacobian"_hash:
0202       case "projector"_hash:
0203         return self().has_impl(key, istate);
0204       default:
0205         return true;
0206     }
0207   }
0208 
0209  public:
0210   /// @anchor track_state_container_track_access
0211   /// @name MultiTrajectory track state (proxy) access and manipulation
0212   ///
0213   /// These methods allow accessing track states, i.e. adding or retrieving a
0214   /// track state proxy that points at a specific track state in the container.
0215   ///
0216   /// @{
0217 
0218   /// Access a read-only point on the trajectory by index.
0219   /// @note Only available if the MultiTrajectory is not read-only
0220   /// @param istate The index to access
0221   /// @return Read only proxy to the stored track state
0222   ConstTrackStateProxy getTrackState(IndexType istate) const {
0223     return {*this, istate};
0224   }
0225 
0226   /// Access a writable point on the trajectory by index.
0227   /// @note Only available if the MultiTrajectory is not read-only
0228   /// @param istate The index to access
0229   /// @return Read-write proxy to the stored track state
0230   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0231   TrackStateProxy getTrackState(IndexType istate) {
0232     return {*this, istate};
0233   }
0234 
0235   /// Add a track state without providing explicit information. Which components
0236   /// of the track state are initialized/allocated can be controlled via @p mask
0237   /// @note Only available if the MultiTrajectory is not read-only
0238   /// @param mask The bitmask that instructs which components to allocate and
0239   ///       which to leave invalid
0240   /// @param iprevious index of the previous state, kInvalid if first
0241   /// @return Index of the newly added track state
0242   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0243   IndexType addTrackState(TrackStatePropMask mask = TrackStatePropMask::All,
0244                           IndexType iprevious = kInvalid) {
0245     return self().addTrackState_impl(mask, iprevious);
0246   }
0247 
0248   /// Add a track state to the container and return a track state proxy to it
0249   /// This effectively calls @c addTrackState and @c getTrackState
0250   /// @note Only available if the track state container is not read-only
0251   /// @return a track state proxy to the newly added track state
0252   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0253   TrackStateProxy makeTrackState(
0254       TrackStatePropMask mask = TrackStatePropMask::All,
0255       IndexType iprevious = kInvalid) {
0256     return getTrackState(addTrackState(mask, iprevious));
0257   }
0258 
0259   /// @}
0260 
0261   /// @anchor track_state_container_iteration
0262   /// @name MultiTrajectory track state iteration
0263   /// @{
0264 
0265   /// Visit all previous states starting at a given endpoint.
0266   ///
0267   /// @param iendpoint  index of the last state
0268   /// @param callable   non-modifying functor to be called with each point
0269   template <typename F>
0270   void visitBackwards(IndexType iendpoint, F&& callable) const;
0271 
0272   /// Apply a function to all previous states starting at a given endpoint.
0273   ///
0274   /// @param iendpoint  index of the last state
0275   /// @param callable   modifying functor to be called with each point
0276   ///
0277   /// @warning If the trajectory contains multiple components with common
0278   ///          points, this can have an impact on the other components.
0279   /// @note Only available if the MultiTrajectory is not read-only
0280   template <typename F, bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0281   void applyBackwards(IndexType iendpoint, F&& callable) {
0282     static_assert(detail_lt::VisitorConcept<F, TrackStateProxy>,
0283                   "Callable needs to satisfy VisitorConcept");
0284 
0285     if (iendpoint == MultiTrajectoryTraits::kInvalid) {
0286       throw std::runtime_error(
0287           "Cannot apply backwards with kInvalid as endpoint");
0288     }
0289 
0290     while (true) {
0291       auto ts = getTrackState(iendpoint);
0292       if constexpr (std::is_same_v<std::invoke_result_t<F, TrackStateProxy>,
0293                                    bool>) {
0294         bool proceed = callable(ts);
0295         // this point has no parent and ends the trajectory, or a break was
0296         // requested
0297         if (!proceed || !ts.hasPrevious()) {
0298           break;
0299         }
0300       } else {
0301         callable(ts);
0302         // this point has no parent and ends the trajectory
0303         if (!ts.hasPrevious()) {
0304           break;
0305         }
0306       }
0307       iendpoint = ts.previous();
0308     }
0309   }
0310 
0311   /// Range for the track states from @p iendpoint to the trajectory start
0312   /// @param iendpoint Trajectory entry point to start from
0313   /// @return Iterator pair to iterate over
0314   /// @note Const version
0315   auto reverseTrackStateRange(IndexType iendpoint) const {
0316     using range_t =
0317         detail_lt::TrackStateRange<true, Derived, MeasurementSizeMax, true>;
0318     if (iendpoint == kInvalid) {
0319       return range_t{};
0320     }
0321 
0322     return range_t{getTrackState(iendpoint)};
0323   }
0324 
0325   /// Range for the track states from @p iendpoint to the trajectory start,
0326   /// i.e from the outside in.
0327   /// @note Only available if the MultiTrajectory is not read-only
0328   /// @param iendpoint Trajectory entry point to start from
0329   /// @return Iterator pair to iterate over
0330   /// @note Mutable version
0331   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0332   auto reverseTrackStateRange(IndexType iendpoint) {
0333     using range_t =
0334         detail_lt::TrackStateRange<true, Derived, MeasurementSizeMax, false>;
0335     if (iendpoint == kInvalid) {
0336       return range_t{};
0337     }
0338 
0339     return range_t{getTrackState(iendpoint)};
0340   }
0341 
0342   /// Range for the track states from @p istartpoint to the trajectory end,
0343   /// i.e from inside out
0344   /// @param istartpoint Trajectory state index for the innermost track
0345   ///        state to start from
0346   /// @return Iterator pair to iterate over
0347   /// @note Const version
0348   auto forwardTrackStateRange(IndexType istartpoint) const {
0349     using range_t =
0350         detail_lt::TrackStateRange<false, Derived, MeasurementSizeMax, true>;
0351     if (istartpoint == kInvalid) {
0352       return range_t{};
0353     }
0354 
0355     return range_t{getTrackState(istartpoint)};
0356   }
0357 
0358   /// Range for the track states from @p istartpoint to the trajectory end,
0359   /// i.e from inside out
0360   /// @note Only available if the MultiTrajectory is not read-only
0361   /// @param istartpoint Trajectory state index for the innermost track
0362   ///        state to start from
0363   /// @return Iterator pair to iterate over
0364   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0365   auto forwardTrackStateRange(IndexType istartpoint) {
0366     using range_t =
0367         detail_lt::TrackStateRange<false, Derived, MeasurementSizeMax, false>;
0368     if (istartpoint == kInvalid) {
0369       return range_t{};
0370     }
0371 
0372     return range_t{getTrackState(istartpoint)};
0373   }
0374 
0375   /// @}
0376 
0377   /// @anchor track_state_container_columns
0378   /// @name MultiTrajectory column management
0379   /// MultiTrajectory can manage a set of common static columns, and dynamic
0380   /// columns that can be added at runtime. This set of methods allows you to
0381   /// manage the dynamic columns.
0382   /// @{
0383 
0384   /// Add a column to the @c MultiTrajectory
0385   /// @tparam T Type of the column values to add
0386   /// @note This takes a string argument rather than a hashed string to maintain
0387   ///       compatibility with backends.
0388   /// @note Only available if the MultiTrajectory is not read-only
0389   template <typename T, bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0390   void addColumn(const std::string& key) {
0391     self().template addColumn_impl<T>(key);
0392   }
0393 
0394   /// Check if a column with a key @p key exists.
0395   /// @param key Key to check for a column with
0396   /// @return True if the column exists, false if not.
0397   bool hasColumn(HashedString key) const { return self().hasColumn_impl(key); }
0398 
0399   /// @}
0400 
0401   /// Clear the @c MultiTrajectory. Leaves the underlying storage untouched
0402   /// @note Only available if the MultiTrajectory is not read-only
0403   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0404   void clear() {
0405     self().clear_impl();
0406   }
0407 
0408   /// Returns the number of track states contained
0409   /// @return The number of track states
0410   IndexType size() const { return self().size_impl(); }
0411 
0412  protected:
0413   // These are internal helper functions which the @c TrackStateProxy class talks to
0414 
0415   /// Check for component existence of @p key in track satet @p istate
0416   /// @param key The key for which to check
0417   /// @param istate The track state index to check
0418   /// @return True if the component exists, false if not
0419   bool has(HashedString key, IndexType istate) const {
0420     return self().has_impl(key, istate);
0421   }
0422 
0423   /// Check for component existence of @p key in track satet @p istate
0424   /// @tparam key The key for which to check
0425   /// @param istate The track state index to check
0426   /// @return True if the component exists, false if not
0427   template <HashedString key>
0428   bool has(IndexType istate) const {
0429     return self().has_impl(key, istate);
0430   }
0431 
0432   /// Retrieve a parameter proxy instance for parameters at a given index
0433   /// @param parIdx Index into the parameter column
0434   /// @return Mutable proxy
0435   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0436   typename TrackStateProxy::Parameters parameters(IndexType parIdx) {
0437     return self().parameters_impl(parIdx);
0438   }
0439 
0440   /// Retrieve a parameter proxy instance for parameters at a given index
0441   /// @param parIdx Index into the parameter column
0442   /// @return Const proxy
0443   typename ConstTrackStateProxy::Parameters parameters(IndexType parIdx) const {
0444     return self().parameters_impl(parIdx);
0445   }
0446 
0447   /// Retrieve a covariance proxy instance for a covariance at a given index
0448   /// @param covIdx Index into the covariance column
0449   /// @return Mutable proxy
0450   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0451   typename TrackStateProxy::Covariance covariance(IndexType covIdx) {
0452     return self().covariance_impl(covIdx);
0453   }
0454 
0455   /// Retrieve a covariance proxy instance for a covariance at a given index
0456   /// @param covIdx Index into the covariance column
0457   /// @return Const proxy
0458   typename ConstTrackStateProxy::Covariance covariance(IndexType covIdx) const {
0459     return self().covariance_impl(covIdx);
0460   }
0461 
0462   /// Retrieve a jacobian proxy instance for a jacobian at a given index
0463   /// @param jacIdx Index into the jacobian column
0464   /// @return Mutable proxy
0465   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0466   typename TrackStateProxy::Covariance jacobian(IndexType jacIdx) {
0467     return self().jacobian_impl(jacIdx);
0468   }
0469 
0470   /// Retrieve a jacobian proxy instance for a jacobian at a given index
0471   /// @param jacIdx Index into the jacobian column
0472   /// @return Const proxy
0473   typename ConstTrackStateProxy::Covariance jacobian(IndexType jacIdx) const {
0474     return self().jacobian_impl(jacIdx);
0475   }
0476 
0477   /// Retrieve a measurement proxy instance for a measurement at a given index
0478   /// @tparam measdim the measurement dimension
0479   /// @param measIdx Index into the measurement column
0480   /// @return Mutable proxy
0481   template <std::size_t measdim, bool RO = ReadOnly,
0482             typename = std::enable_if_t<!RO>>
0483   typename TrackStateProxy::template Measurement<measdim> measurement(
0484       IndexType measIdx) {
0485     return self().template measurement_impl<measdim>(measIdx);
0486   }
0487 
0488   /// Retrieve a measurement proxy instance for a measurement at a given index
0489   /// @tparam measdim the measurement dimension
0490   /// @param measIdx Index into the measurement column
0491   /// @return Const proxy
0492   template <std::size_t measdim>
0493   typename ConstTrackStateProxy::template Measurement<measdim> measurement(
0494       IndexType measIdx) const {
0495     return self().template measurement_impl<measdim>(measIdx);
0496   }
0497 
0498   /// Retrieve a measurement covariance proxy instance for a measurement at a
0499   /// given index
0500   /// @tparam measdim the measurement dimension
0501   /// @param covIdx Index into the measurement covariance column
0502   /// @return Mutable proxy
0503   template <std::size_t measdim, bool RO = ReadOnly,
0504             typename = std::enable_if_t<!RO>>
0505   typename TrackStateProxy::template MeasurementCovariance<measdim>
0506   measurementCovariance(IndexType covIdx) {
0507     return self().template measurementCovariance_impl<measdim>(covIdx);
0508   }
0509 
0510   /// Retrieve a measurement covariance proxy instance for a measurement at a
0511   /// given index
0512   /// @param covIdx Index into the measurement covariance column
0513   /// @return Const proxy
0514   template <std::size_t measdim>
0515   constexpr
0516       typename ConstTrackStateProxy::template MeasurementCovariance<measdim>
0517       measurementCovariance(IndexType covIdx) const {
0518     return self().template measurementCovariance_impl<measdim>(covIdx);
0519   }
0520 
0521   /// Get the calibrated measurement size for a track state
0522   /// @param istate The track state
0523   /// @return the calibrated size
0524   IndexType calibratedSize(IndexType istate) const {
0525     return self().calibratedSize_impl(istate);
0526   }
0527 
0528   /// Share a shareable component from between track state.
0529   /// @param iself The track state index to share "into"
0530   /// @param iother The track state index to share from
0531   /// @param shareSource Which component to share from
0532   /// @param shareTarget Which component to share as. This doesn't have to be the same
0533   ///                    as @p shareSource, e.g. predicted can be shared as filtered.
0534   /// @note Shareable components are predicted, filtered, smoothed, calibrated, jacobian,
0535   ///       or projector. See @c TrackStatePropMask.
0536   /// @note The track states both need to be stored in the
0537   ///       same @c MultiTrajectory instance
0538   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0539   void shareFrom(IndexType iself, IndexType iother,
0540                  TrackStatePropMask shareSource,
0541                  TrackStatePropMask shareTarget) {
0542     self().shareFrom_impl(iself, iother, shareSource, shareTarget);
0543   }
0544 
0545   /// Unset an optional track state component
0546   /// @param target The component to unset
0547   /// @param istate The track state index to operate on
0548   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0549   void unset(TrackStatePropMask target, IndexType istate) {
0550     self().unset_impl(target, istate);
0551   }
0552 
0553   /// Add additional components to an existing track state
0554   /// @note Only available if the track state container is not read-only
0555   /// @param istate The track state index to alter
0556   /// @param mask The bitmask that instructs which components to allocate
0557   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0558   void addTrackStateComponents(IndexType istate, TrackStatePropMask mask) {
0559     self().addTrackStateComponents_impl(istate, mask);
0560   }
0561 
0562   /// Retrieve a mutable reference to a component
0563   /// @tparam T The type of the component to access
0564   /// @tparam key String key for the component to access
0565   /// @param istate The track state index to operate on
0566   /// @return Mutable reference to the component given by @p key
0567   template <typename T, HashedString key, bool RO = ReadOnly,
0568             typename = std::enable_if_t<!RO>>
0569   T& component(IndexType istate) {
0570     assert(checkOptional(key, istate));
0571     return *std::any_cast<T*>(self().component_impl(key, istate));
0572   }
0573 
0574   /// Retrieve a mutable reference to a component
0575   /// @tparam T The type of the component to access
0576   /// @param key String key for the component to access
0577   /// @param istate The track state index to operate on
0578   /// @return Mutable reference to the component given by @p key
0579   template <typename T, bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0580   T& component(HashedString key, IndexType istate) {
0581     assert(checkOptional(key, istate));
0582     return *std::any_cast<T*>(self().component_impl(key, istate));
0583   }
0584 
0585   /// Retrieve a const reference to a component
0586   /// @tparam T The type of the component to access
0587   /// @tparam key String key for the component to access
0588   /// @param istate The track state index to operate on
0589   /// @return Const reference to the component given by @p key
0590   template <typename T, HashedString key>
0591   const T& component(IndexType istate) const {
0592     assert(checkOptional(key, istate));
0593     return *std::any_cast<const T*>(self().component_impl(key, istate));
0594   }
0595 
0596   /// Retrieve a const reference to a component
0597   /// @tparam T The type of the component to access
0598   /// @param key String key for the component to access
0599   /// @param istate The track state index to operate on
0600   /// @return Const reference to the component given by @p key
0601   template <typename T>
0602   const T& component(HashedString key, IndexType istate) const {
0603     assert(checkOptional(key, istate));
0604     return *std::any_cast<const T*>(self().component_impl(key, istate));
0605   }
0606 
0607   /// Allocate storage for a calibrated measurement of specified dimension
0608   /// @param istate The track state to store for
0609   /// @param measdim the dimension of the measurement to store
0610   /// @note Is a noop if the track state already has an allocation
0611   ///       an the dimension is the same.
0612   void allocateCalibrated(IndexType istate, std::size_t measdim) {
0613     throw_assert(measdim > 0 && measdim <= eBoundSize,
0614                  "Invalid measurement dimension detected");
0615 
0616     self().allocateCalibrated_impl(istate, measdim);
0617   }
0618 
0619   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0620   void setUncalibratedSourceLink(IndexType istate, SourceLink sourceLink) {
0621     self().setUncalibratedSourceLink_impl(istate, std::move(sourceLink));
0622   }
0623 
0624   SourceLink getUncalibratedSourceLink(IndexType istate) const {
0625     return self().getUncalibratedSourceLink_impl(istate);
0626   }
0627 
0628   const Surface* referenceSurface(IndexType istate) const {
0629     return self().referenceSurface_impl(istate);
0630   }
0631 
0632   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0633   void setReferenceSurface(IndexType istate,
0634                            std::shared_ptr<const Surface> surface) {
0635     self().setReferenceSurface_impl(istate, std::move(surface));
0636   }
0637 
0638  private:
0639   template <typename T, bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0640   void copyDynamicFrom(IndexType dstIdx, const T& src, IndexType srcIdx) {
0641     const auto& dynamicKeys = src.self().dynamicKeys_impl();
0642     for (const auto key : dynamicKeys) {
0643       std::any srcPtr = src.self().component_impl(key, srcIdx);
0644       self().copyDynamicFrom_impl(dstIdx, key, srcPtr);
0645     }
0646   }
0647 };
0648 
0649 }  // namespace Acts
0650 
0651 #include "Acts/EventData/MultiTrajectory.ipp"