Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-21 08:01:53

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