Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-19 08:32:18

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/TrackParametrization.hpp"
0012 #include "Acts/EventData/BoundTrackParameters.hpp"
0013 #include "Acts/EventData/MultiTrajectory.hpp"
0014 #include "Acts/EventData/MultiTrajectoryBackendConcept.hpp"
0015 #include "Acts/EventData/ParticleHypothesis.hpp"
0016 #include "Acts/EventData/TrackContainerBackendConcept.hpp"
0017 #include "Acts/EventData/TrackProxyCommon.hpp"
0018 #include "Acts/EventData/TrackProxyConcept.hpp"
0019 #include "Acts/EventData/TrackStatePropMask.hpp"
0020 #include "Acts/Utilities/HashedString.hpp"
0021 #include "Acts/Utilities/Holders.hpp"
0022 #include "Acts/Utilities/TypeTraits.hpp"
0023 
0024 #include <iterator>
0025 
0026 namespace Acts {
0027 
0028 template <TrackContainerBackend track_container_t,
0029           CommonMultiTrajectoryBackend traj_t,
0030           template <typename> class holder_t>
0031   requires HolderFor<holder_t, track_container_t> && HolderFor<holder_t, traj_t>
0032 class TrackContainer;
0033 
0034 template <bool read_only>
0035 class AnyTrack;
0036 
0037 /// Proxy class representing a single track.
0038 /// This class provides a **view** into an associated @ref TrackContainer, and
0039 /// has **reference semantics**. You can think of it as a pointer to a vector
0040 /// of tracks, which exposes an object-oriented interface for accessing the
0041 /// track properties.
0042 ///
0043 /// @tparam track_container_t the container backend
0044 /// @tparam trajectory_t the track state container backend
0045 /// @tparam holder_t ownership management class for the backend
0046 /// @tparam read_only true if this track container is not mutable
0047 template <typename track_container_t, typename trajectory_t,
0048           template <typename> class holder_t, bool read_only = true>
0049 class TrackProxy
0050     : public TrackProxyCommon<
0051           TrackProxy<track_container_t, trajectory_t, holder_t, read_only>,
0052           typename track_container_t::IndexType, read_only> {
0053   using Base = TrackProxyCommon<
0054       TrackProxy<track_container_t, trajectory_t, holder_t, read_only>,
0055       typename track_container_t::IndexType, read_only>;
0056 
0057  public:
0058   /// Indicates whether this track proxy is read-only or if it can be
0059   /// modified
0060   static constexpr bool ReadOnly = read_only;
0061 
0062   /// The track container backend given as a template parameter
0063   using Container = track_container_t;
0064 
0065   /// The track state container backend given as a template parameter
0066   using Trajectory = trajectory_t;
0067 
0068   /// The index type of the track container
0069   using IndexType = TrackIndexType;
0070 
0071   /// Sentinel value that indicates an invalid index
0072   static constexpr IndexType kInvalid = kTrackIndexInvalid;
0073 
0074   /// Alias for the mutable version of this track proxy, with the same backends
0075   using MutableTrackProxy =
0076       TrackProxy<track_container_t, trajectory_t, holder_t, false>;
0077 
0078   /// Alias for the const version of this track proxy, with the same backends
0079   using ConstTrackProxy =
0080       TrackProxy<track_container_t, trajectory_t, holder_t, true>;
0081 
0082   /// Alias for an associated const track proxy, with the same backends
0083   using ConstProxyType = ConstTrackProxy;
0084 
0085   /// Alias for an associated mutable track state proxy, with the same backends
0086   using TrackStateProxy = typename Trajectory::TrackStateProxy;
0087 
0088   /// Alias for an associated const track state proxy, with the same backends
0089   using ConstTrackStateProxy = typename Trajectory::ConstTrackStateProxy;
0090 
0091   /// Map-type for a bound parameter vector. This has reference semantics, i.e.
0092   /// points at a matrix by an internal pointer.
0093   using Parameters =
0094       typename detail_tsp::FixedSizeTypes<eBoundSize, false>::CoefficientsMap;
0095 
0096   /// Same as @ref Parameters, but with const semantics
0097   using ConstParameters =
0098       typename detail_tsp::FixedSizeTypes<eBoundSize, true>::CoefficientsMap;
0099 
0100   /// Map-type for a bound covariance. This has reference semantics, i.e.
0101   /// points at a matrix by an internal pointer.
0102   using Covariance =
0103       typename detail_tsp::FixedSizeTypes<eBoundSize, false>::CovarianceMap;
0104 
0105   /// Same as @ref Covariance, but with const semantics
0106   using ConstCovariance =
0107       typename detail_tsp::FixedSizeTypes<eBoundSize, true>::CovarianceMap;
0108 
0109 #ifndef DOXYGEN
0110   friend TrackContainer<Container, Trajectory, holder_t>;
0111   friend MutableTrackProxy;
0112   friend ConstTrackProxy;
0113   // Track proxies are friends, not food!
0114   template <typename A, typename B, template <typename> class H, bool R>
0115   friend class TrackProxy;
0116   template <bool R>
0117   friend class AnyTrackProxy;
0118 #endif
0119 
0120   /// @anchor track_proxy_construct
0121   /// @name Constructors and assignment operator
0122   ///
0123   /// Public constructors and assignment operators for @c TrackProxy only
0124   /// allow construction from another @c TrackProxy. You should generally
0125   /// not have to construct @c TrackProxy manually.
0126   ///
0127   /// @{
0128 
0129   /// Copy constructor: const to const or mutable to mutable
0130   /// @param other the other track proxy
0131   TrackProxy(const TrackProxy& other) = default;
0132 
0133   /// Copy assignment operator: const to const or mutable to mutable
0134   /// @param other the other track proxy
0135   /// @return reference to this track proxy
0136   TrackProxy& operator=(const TrackProxy& other) = default;
0137 
0138   /// Constructor from mutable track proxy
0139   /// @note Only available if the track proxy is read-only
0140   /// @param other the other track proxy
0141   explicit TrackProxy(const MutableTrackProxy& other)
0142     requires ReadOnly
0143       : m_container{other.m_container}, m_index{other.m_index} {}
0144 
0145   /// Copy assignment operator from mutable track proxy
0146   /// @note Only available if the track proxy is read-only
0147   /// @param other the other track proxy
0148   /// @return reference to this track proxy
0149   TrackProxy& operator=(const MutableTrackProxy& other)
0150     requires ReadOnly
0151   {
0152     m_container = other.m_container;
0153     m_index = other.m_index;
0154     return *this;
0155   }
0156 
0157   /// @}
0158 
0159   /// Equality operator with another track proxy
0160   /// Checks the container identity and the track index
0161   /// @param other Other track proxy to compare with
0162   /// @return True if the track proxies refer to the same track
0163   bool operator==(const TrackProxy& other) const {
0164     return &(*m_container) == &(*other.m_container) && m_index == other.m_index;
0165   }
0166 
0167   /// @anchor track_proxy_props
0168   /// @name TrackProxy properties
0169   /// Methods that give access to the properties of a track represented by
0170   /// @c TrackProxy.
0171   ///
0172   /// Many of these methods come in a @c const and a non-@c const version. The
0173   /// non-@c const version is only available if you have an instance of
0174   /// @c TrackProxy that does not have the @c read_only template parameter set to
0175   /// @c true, even if you hold it as an lvalue.
0176   ///
0177   /// @{
0178 
0179   /// Get the reference surface of the track (e.g. the perigee)
0180   /// @return the reference surface
0181   const Surface& referenceSurface() const {
0182     return *m_container->container().referenceSurface_impl(m_index);
0183   }
0184 
0185   // NOLINTBEGIN(performance-unnecessary-value-param)
0186   // looks like a false-positive. clang-tidy believes `srf` is not movable.
0187   /// Set a new reference surface for this track
0188   /// @param srf The surface to set
0189   void setReferenceSurface(std::shared_ptr<const Surface> srf)
0190     requires(!ReadOnly)
0191   {
0192     m_container->container().setReferenceSurface_impl(m_index, std::move(srf));
0193   }
0194   // NOLINTEND(performance-unnecessary-value-param)
0195 
0196   /// Returns whether the track has a reference surface or not
0197   /// @return whether a surface exists or not
0198   bool hasReferenceSurface() const {
0199     // @TODO: This could be more efficient
0200     return m_container->container().referenceSurface_impl(m_index) != nullptr;
0201   }
0202 
0203   /// Get the parameters of the track at the reference surface (e.g. perigee).
0204   /// Const version
0205   /// @return Proxy vector for the parameters
0206   ConstParameters parameters() const {
0207     return m_container->parameters(m_index);
0208   }
0209 
0210   /// Get the covariance of the track at the reference surface (e.g. perigee).
0211   /// Const version
0212   /// @return Proxy matrix for the covariance
0213   ConstCovariance covariance() const {
0214     return m_container->covariance(m_index);
0215   }
0216 
0217   /// Get the parameters of the track at the reference surface (e.g. perigee).
0218   /// Mutable version
0219   /// @note Only available if the track proxy is not read-only
0220   /// @return Proxy vector for the parameters
0221   Parameters parameters()
0222     requires(!ReadOnly)
0223   {
0224     return m_container->parameters(m_index);
0225   }
0226 
0227   /// Get the covariance of the track at the reference surface (e.g. perigee).
0228   /// Mutable version
0229   /// @note Only available if the track proxy is not read-only
0230   /// @return Proxy matrix for the covariance
0231   Covariance covariance()
0232     requires(!ReadOnly)
0233   {
0234     return m_container->covariance(m_index);
0235   }
0236 
0237   /// Get the particle hypothesis
0238   /// @return the particle hypothesis
0239   ParticleHypothesis particleHypothesis() const {
0240     return m_container->container().particleHypothesis_impl(m_index);
0241   }
0242 
0243   /// Set a new particle hypothesis for this track
0244   /// @note Only available if the track proxy is not read-only
0245   /// @param particleHypothesis The particle hypothesis to set
0246   void setParticleHypothesis(const ParticleHypothesis& particleHypothesis)
0247     requires(!ReadOnly)
0248   {
0249     m_container->container().setParticleHypothesis_impl(m_index,
0250                                                         particleHypothesis);
0251   }
0252 
0253   using Base::absoluteMomentum;
0254   using Base::charge;
0255   using Base::chi2;
0256   using Base::direction;
0257   using Base::fourMomentum;
0258   using Base::isForwardLinked;
0259   using Base::loc0;
0260   using Base::loc1;
0261   using Base::momentum;
0262   using Base::nDoF;
0263   using Base::nHoles;
0264   using Base::nMeasurements;
0265   using Base::nOutliers;
0266   using Base::nSharedHits;
0267   using Base::nSplitHits;
0268   using Base::phi;
0269   using Base::qOverP;
0270   using Base::stemIndex;
0271   using Base::theta;
0272   using Base::time;
0273   using Base::tipIndex;
0274   using Base::transverseMomentum;
0275 
0276   /// Return the number of track states associated to this track
0277   /// @note This is calculated by iterating over the track states which is
0278   ///       somewhat expensive. Consider caching this value if you need It
0279   ///       more than once.
0280   /// @return The number of track states
0281   unsigned int nTrackStates() const {
0282     // @TODO: This should probably be cached, distance is expensive
0283     //        without random access
0284     if (tipIndex() == kInvalid) {
0285       // no tip index -> no track states
0286       return 0;
0287     }
0288     auto tsRange = trackStatesReversed();
0289     return std::distance(tsRange.begin(), tsRange.end());
0290   }
0291 
0292   /// Return the index of this track in the track container
0293   /// @note This is separate from the tip index
0294   /// @return the track index
0295   IndexType index() const { return m_index; }
0296 
0297   /// @}
0298 
0299   /// @anchor track_proxy_track_states
0300   /// @name TrackProxy track state access
0301   /// Methods that give access to the track states of a track represented by @c TrackProxy.
0302   /// @{
0303 
0304   /// Return a const track state proxy to the outermost track state
0305   /// @return The outermost track state proxy
0306   ConstTrackStateProxy outermostTrackState() const {
0307     return m_container->trackStateContainer().getTrackState(tipIndex());
0308   }
0309 
0310   /// Return a mutable track state proxy to the outermost track state
0311   /// @return The outermost track state proxy
0312   TrackStateProxy outermostTrackState()
0313     requires(!ReadOnly)
0314   {
0315     return m_container->trackStateContainer().getTrackState(tipIndex());
0316   }
0317 
0318   /// Return a const track state proxy to the innermost track state
0319   /// @note This is only available, if the track is forward linked
0320   /// @return The innermost track state proxy
0321   auto innermostTrackState() const {
0322     using proxy_t = decltype(m_container->trackStateContainer().getTrackState(
0323         std::declval<IndexType>()));
0324 
0325     IndexType stem = component<IndexType, detail_tp::kStemIndexKey>();
0326     if (stem == kInvalid) {
0327       return std::optional<proxy_t>{};
0328     } else {
0329       return std::optional<proxy_t>{
0330           m_container->trackStateContainer().getTrackState(stem)};
0331     }
0332   }
0333 
0334   /// Return a mutable track state proxy to the innermost track state
0335   /// @note This is only available, if the track is forward linked
0336   /// @note Only available if the track proxy is not read-only
0337   /// @return The innermost track state proxy
0338   auto innermostTrackState()
0339     requires(!ReadOnly)
0340   {
0341     using proxy_t = decltype(m_container->trackStateContainer().getTrackState(
0342         std::declval<IndexType>()));
0343 
0344     IndexType stem = component<IndexType>(detail_tp::kStemIndexKey);
0345     if (stem == kInvalid) {
0346       return std::optional<proxy_t>{};
0347     } else {
0348       return std::optional<proxy_t>{
0349           m_container->trackStateContainer().getTrackState(stem)};
0350     }
0351   }
0352 
0353   /// Get a range over the track states of this track. Return value is
0354   /// compatible with range based for loop. Const version
0355   /// @note This range is from the outside inwards!
0356   /// @return Track state range to iterate over
0357   auto trackStatesReversed() const {
0358     return m_container->reverseTrackStateRange(m_index);
0359   }
0360 
0361   /// Get a range over the track states of this track. Return value is
0362   /// compatible with range based for loop. Mutable version
0363   /// @note Only available if the track proxy is not read-only
0364   /// @note This range is from the outside inwards!
0365   /// @return Track state range to iterate over
0366   auto trackStatesReversed()
0367     requires(!ReadOnly)
0368   {
0369     return m_container->reverseTrackStateRange(m_index);
0370   }
0371 
0372   /// Get a range over the track states of this track. Return value is
0373   /// compatible with range based for loop. This overload returns a const-only
0374   /// track state range, which means you cannot modify the track states obtained
0375   /// in the iteration.
0376   /// @note This range is from the inside out!
0377   /// @warning This access direction is only possible if the track states are
0378   ///          **forward-linked**.
0379   /// @return Track state range to iterate over
0380   auto trackStates() const {
0381     return m_container->forwardTrackStateRange(m_index);
0382   }
0383 
0384   /// Get a range over the track states of this track.
0385   /// Return value is compatible with range based for loop.
0386   /// This overload returns a mutable track state range, which means you
0387   /// can modify the track states obtained in the iteration.
0388   /// @note Only available if the track proxy is not read-only
0389   /// @note This range is from the inside out!
0390   /// @warning This access direction is only possible if the track states are
0391   ///          **forward-linked**.
0392   /// @return Track state range to iterate over
0393   auto trackStates()
0394     requires(!ReadOnly)
0395   {
0396     return m_container->forwardTrackStateRange(m_index);
0397   }
0398 
0399   /// @}
0400 
0401   /// @anchor track_proxy_track_state_manipulation
0402   /// @name TrackProxy track state manipulation
0403   /// Methods that manipulate the track states of a track represented by @c
0404   /// TrackProxy.
0405   ///
0406   /// **Copy Methods Overview:**
0407   ///
0408   /// Three main copy methods are available with different behaviors:
0409   /// - @c copyFrom(): Deep copy including all track states (creates new track
0410   ///                 states)
0411   /// - @c copyFromWithoutStates(): Copy only track properties, invalidate
0412   ///                               track state indices
0413   /// - @c copyFromShallow(): Shallow copy sharing the same track states (copy
0414   ///                         indices only)
0415   ///
0416   /// Choose based on your needs:
0417   /// - Use @c copyFrom() for independent track copies with separate track
0418   ///   states
0419   /// - Use @c copyFromWithoutStates() to update track metadata without
0420   ///   affecting trajectories
0421   /// - Use @c copyFromShallow() for lightweight copies when track states can
0422   ///   be shared
0423   /// @{
0424 
0425   /// Forward connect a track.
0426   /// This means setting indices from the inside out on all track states.
0427   /// @note Only available if the track proxy is not read-only
0428   void linkForward()
0429     requires(!ReadOnly)
0430   {
0431     IndexType last = kInvalid;
0432     for (auto ts : trackStatesReversed()) {
0433       ts.template component<IndexType>(detail_tp::kNextKey) = last;
0434       last = ts.index();
0435     }
0436     stemIndex() = last;
0437   }
0438 
0439   /// Append a track state to this track.
0440   /// This will modify the tip index to point at the newly created track state,
0441   /// which will be directly after the previous track state at tip index.
0442   /// @note Only available if the track proxy is not read-only
0443   /// @param mask The allocation prop mask for the new track state
0444   /// @return The newly added track state
0445   auto appendTrackState(TrackStatePropMask mask = TrackStatePropMask::All)
0446     requires(!ReadOnly)
0447   {
0448     auto& tsc = m_container->trackStateContainer();
0449     auto ts = tsc.makeTrackState(mask, tipIndex());
0450     tipIndex() = ts.index();
0451     return ts;
0452   }
0453 
0454   /// Create a complete deep copy of another track, including all track states.
0455   /// This creates new track states in the destination trajectory and copies
0456   /// all data from the source track states. The track state sequence order
0457   /// is preserved.
0458   ///
0459   /// **Implementation details:**
0460   /// - Track states are initially copied in reversed order for efficiency
0461   /// - The track state links are then updated using reverseTrackStates()
0462   /// - As a consequence, the resulting track is forward-linked
0463   ///
0464   /// **What gets copied:**
0465   /// - All track-level properties (parameters, covariance, particle hypothesis,
0466   ///   etc.)
0467   /// - Reference surface (shared pointer is copied)
0468   /// - Track summary data (nMeasurements, nHoles, chi2, etc.)
0469   /// - All dynamic track columns
0470   /// - Complete sequence of track states with all their data
0471   /// - All dynamic track state columns
0472   ///
0473   /// **Result:**
0474   /// - The destination track will have newly created track states
0475   /// - tipIndex() and stemIndex() will point to the new track
0476   /// states
0477   /// - Track state indices will be different from the source
0478   /// - All track state data will be identical to the source
0479   /// - The track will be forward-linked (stemIndex() will be valid)
0480   ///
0481   /// @note Only available if the track proxy is not read-only
0482   /// @note Both track containers must have compatible dynamic columns
0483   /// @tparam track_proxy_t the other track proxy's type
0484   /// @param other The source track proxy to copy from
0485   template <TrackProxyConcept track_proxy_t>
0486   void copyFrom(const track_proxy_t& other)
0487     requires(!ReadOnly)
0488   {
0489     copyFromWithoutStates(other);
0490 
0491     // append track states (cheap), but they're in the wrong order
0492     for (const auto& srcTrackState : other.trackStatesReversed()) {
0493       auto destTrackState = appendTrackState(srcTrackState.getMask());
0494       destTrackState.copyFrom(srcTrackState, Acts::TrackStatePropMask::All,
0495                               true);
0496     }
0497 
0498     // reverse using standard linked list reversal algorithm
0499     reverseTrackStates();
0500   }
0501 
0502   /// Copy track-level properties from another track, but not the track states.
0503   /// This copies all track metadata and properties but leaves the track state
0504   /// sequence unchanged. Useful when you want to copy track properties to an
0505   /// existing track that may already have track states.
0506   ///
0507   /// **What gets copied:**
0508   /// - Track parameters at reference surface
0509   /// - Covariance matrix at reference surface
0510   /// - Particle hypothesis
0511   /// - Reference surface (shared pointer is copied)
0512   /// - Track summary data (nMeasurements, nHoles, nOutliers, nSharedHits,
0513   /// nSplitHits, chi2, nDoF)
0514   /// - All dynamic track columns
0515   ///
0516   /// **What does NOT get copied:**
0517   /// - Track states (existing track states remain unchanged in the container)
0518   ///
0519   /// **Result:**
0520   /// - All track-level properties are updated to match the source
0521   /// - tipIndex() and stemIndex() are set to kInvalid (track states
0522   /// become inaccessible)
0523   /// - Existing track states remain in the container but are no longer linked
0524   /// to this track
0525   /// - nTrackStates() will return 0 due to invalid indices
0526   ///
0527   /// @note Only available if the track proxy is not read-only
0528   /// @note Both track containers must have compatible dynamic columns
0529   /// @tparam track_proxy_t the other track proxy's type
0530   /// @param other The source track proxy to copy properties from
0531   template <TrackProxyConcept track_proxy_t>
0532   void copyFromWithoutStates(const track_proxy_t& other)
0533     requires(!ReadOnly)
0534   {
0535     setParticleHypothesis(other.particleHypothesis());
0536 
0537     if (other.hasReferenceSurface()) {
0538       setReferenceSurface(other.referenceSurface().getSharedPtr());
0539       parameters() = other.parameters();
0540       covariance() = other.covariance();
0541     } else {
0542       setReferenceSurface(nullptr);
0543     }
0544 
0545     nMeasurements() = other.nMeasurements();
0546     nHoles() = other.nHoles();
0547     nOutliers() = other.nOutliers();
0548     nSharedHits() = other.nSharedHits();
0549     // The split hit column is optional: copy it only if both sides have it
0550     if constexpr (requires { other.nSplitHits(); }) {
0551       if (hasColumn(detail_tp::kSplitHitsKey) &&
0552           other.hasColumn(detail_tp::kSplitHitsKey)) {
0553         nSplitHits() = other.nSplitHits();
0554       }
0555     }
0556     chi2() = other.chi2();
0557     nDoF() = other.nDoF();
0558 
0559     m_container->copyDynamicFrom(m_index, other.m_container->container(),
0560                                  other.m_index);
0561 
0562     tipIndex() = kInvalid;
0563     stemIndex() = kInvalid;
0564   }
0565 
0566   /// Create a shallow copy from another track, sharing the same track states.
0567   /// This copies all track-level properties and makes the destination track
0568   /// point to the same track state sequence as the source. The track states
0569   /// themselves are not duplicated - both tracks will reference the same
0570   /// track state objects in memory.
0571   ///
0572   /// **What gets copied:**
0573   /// - All track-level properties (parameters, covariance, particle hypothesis,
0574   /// etc.)
0575   /// - Reference surface (shared pointer is copied)
0576   /// - Track summary data (nMeasurements, nHoles, chi2, etc.)
0577   /// - All dynamic track columns
0578   /// - tipIndex() and stemIndex() (track state linking information)
0579   ///
0580   /// **What gets shared (not duplicated):**
0581   /// - Track states (both tracks reference the same track state objects)
0582   ///
0583   /// **Result:**
0584   /// - The destination track will have the same nTrackStates() as the source
0585   /// - Both tracks will iterate over the same track state sequence
0586   /// - Modifications to track states will be visible in both tracks
0587   /// - Track state indices will be identical between tracks
0588   /// - The destination track will have a different track index than the source
0589   ///
0590   /// @warning Modifying track states through either track will affect both tracks
0591   ///          since they share the same track state objects
0592   /// @warning It is the user's responsibility to ensure that the tip and stem
0593   ///          indices from the source track are valid in the destination
0594   ///          track's track state container. No validation is performed -
0595   ///          invalid indices will lead to undefined behavior when accessing
0596   ///          track states
0597   /// @note Only available if the track proxy is not read-only
0598   /// @note Both track containers must have compatible dynamic columns
0599   /// @tparam track_proxy_t the other track proxy's type
0600   /// @param other The source track proxy to create a shallow copy from
0601   template <TrackProxyConcept track_proxy_t>
0602   void copyFromShallow(const track_proxy_t& other)
0603     requires(!ReadOnly)
0604   {
0605     copyFromWithoutStates(other);
0606     tipIndex() = other.tipIndex();
0607     stemIndex() = other.stemIndex();
0608   }
0609 
0610   /// Reverse the ordering of track states for this track
0611   /// Afterwards, the previous endpoint of the track state sequence will be
0612   /// the "innermost" track state
0613   /// @note Only available if the track proxy is not read-only
0614   /// @note This is dangerous with branching track state sequences, as it will break them
0615   /// @note This also automatically forward-links the track!
0616   /// @param invertJacobians Whether to invert the Jacobians of the track states
0617   void reverseTrackStates(bool invertJacobians = false)
0618     requires(!ReadOnly)
0619   {
0620     IndexType current = tipIndex();
0621     IndexType next = kInvalid;
0622     IndexType prev = kInvalid;
0623 
0624     stemIndex() = tipIndex();
0625 
0626     // @TODO: Maybe refactor to not need this variable if invertJacobians == false
0627     BoundMatrix nextJacobian;
0628 
0629     while (current != kInvalid) {
0630       auto ts = m_container->trackStateContainer().getTrackState(current);
0631       prev = ts.previous();
0632       ts.template component<IndexType>(detail_tp::kNextKey) = prev;
0633       ts.previous() = next;
0634       if (invertJacobians) {
0635         if (next != kInvalid) {
0636           BoundMatrix curJacobian = ts.jacobian();
0637           ts.jacobian() = nextJacobian.inverse();
0638           nextJacobian = curJacobian;
0639         } else {
0640           nextJacobian = ts.jacobian();
0641           ts.jacobian().setZero();
0642         }
0643       }
0644       next = current;
0645       tipIndex() = current;
0646       current = prev;
0647     }
0648   }
0649 
0650   /// @}
0651 
0652   /// @anchor track_proxy_generic_component
0653   /// @name TrackProxy generic component access
0654   /// Methods that give access to generic components of a track represented by
0655   /// @c TrackProxy.  Internally, a compile-time hash of the component name is
0656   /// used to identify which component is being requested. Most of the named
0657   /// methods in @ref track_proxy_props "TrackProxy properties" use these
0658   /// methods to retrieve the actual data.
0659   ///
0660   /// A number of overloads exist, where you can either supply the
0661   /// @ref HashedString @c key as a template parameter or a runtime argument.  The
0662   /// former has the advantage of being guaranteed to be evaluated at
0663   /// compile-time.
0664   ///
0665   /// @{
0666 
0667   /// Retrieve a mutable reference to a component
0668   /// @tparam T The type of the component to access
0669   /// @tparam key String key for the component to access
0670   /// @return Mutable reference to the component given by @p key
0671   template <typename T, HashedString key>
0672   constexpr T& component()
0673     requires(!ReadOnly)
0674   {
0675     return m_container->template component<T, key>(m_index);
0676   }
0677 
0678   /// Retrieve a mutable reference to a component
0679   /// @tparam T The type of the component to access
0680   /// @param key String key for the component to access
0681   /// @return Mutable reference to the component given by @p key
0682   template <typename T>
0683   constexpr T& component(HashedString key)
0684     requires(!ReadOnly)
0685   {
0686     return m_container->template component<T>(key, m_index);
0687   }
0688 
0689   /// Retrieve a mutable reference to a component
0690   /// @tparam T The type of the component to access
0691   /// @param key String key for the component to access
0692   /// @note This might hash the @p key at runtime instead of compile-time
0693   /// @return Mutable reference to the component given by @p key
0694   template <typename T>
0695   constexpr T& component(std::string_view key)
0696     requires(!ReadOnly)
0697   {
0698     return m_container->template component<T>(hashStringDynamic(key), m_index);
0699   }
0700 
0701   /// Retrieve a const reference to a component
0702   /// @tparam T The type of the component to access
0703   /// @tparam key String key for the component to access
0704   /// @return Const reference to the component given by @p key
0705   template <typename T, HashedString key>
0706   constexpr const T& component() const {
0707     return m_container->template component<T, key>(m_index);
0708   }
0709 
0710   /// Check whether a dynamic column exists
0711   /// @param key String key for the component to check
0712   /// @return whether the column exists
0713   bool hasColumn(HashedString key) const { return m_container->hasColumn(key); }
0714 
0715   /// Retrieve a const reference to a component
0716   /// @tparam T The type of the component to access
0717   /// @param key String key for the component to access
0718   /// @return Const reference to the component given by @p key
0719   template <typename T>
0720   constexpr const T& component(HashedString key) const {
0721     return m_container->template component<T>(key, m_index);
0722   }
0723 
0724   /// Retrieve a const reference to a component
0725   /// @tparam T The type of the component to access
0726   /// @param key String key for the component to access
0727   /// @note This might hash the @p key at runtime instead of compile-time
0728   /// @return Const reference to the component given by @p key
0729   template <typename T>
0730   constexpr const T& component(std::string_view key) const {
0731     return m_container->template component<T>(hashStringDynamic(key), m_index);
0732   }
0733 
0734   /// @}
0735 
0736   /// Return the track parameters at the reference surface
0737   /// @note The parameters are created on the fly
0738   /// @return the track parameters
0739   BoundTrackParameters createParametersAtReference() const {
0740     return BoundTrackParameters(referenceSurface().getSharedPtr(), parameters(),
0741                                 covariance(), particleHypothesis());
0742   }
0743 
0744   /// Convert a track state into track parameters
0745   /// @note The parameters are created on the fly
0746   /// @param trackState Track state to convert to parameters
0747   /// @return the track parameters
0748   BoundTrackParameters createParametersFromState(
0749       const ConstTrackStateProxy& trackState) const {
0750     return BoundTrackParameters(trackState.referenceSurface().getSharedPtr(),
0751                                 trackState.parameters(),
0752                                 trackState.covariance(), particleHypothesis());
0753   }
0754 
0755   /// Return a reference to the track container backend, mutable version.
0756   /// @note Only available if the track proxy is not read-only
0757   /// @return reference to the track container backend
0758   auto& container()
0759     requires(!ReadOnly)
0760   {
0761     return *m_container;
0762   }
0763 
0764   /// Return a reference to the track container backend, const version.
0765   /// @return reference to the track container backend
0766   const auto& container() const { return *m_container; }
0767 
0768  private:
0769   TrackProxy(
0770       const_if_t<ReadOnly, TrackContainer<Container, Trajectory, holder_t>>&
0771           container,
0772       IndexType itrack)
0773       : m_container{&container}, m_index{itrack} {}
0774 
0775   detail_lt::TransitiveConstPointer<
0776       const_if_t<ReadOnly, TrackContainer<Container, Trajectory, holder_t>>>
0777       m_container;
0778   IndexType m_index;
0779 };
0780 
0781 }  // namespace Acts