Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-11 07:49:44

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