Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-20 07:51:14

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