Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-21 07:46:23

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