Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-02 07:32:02

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::phi;
0268   using Base::qOverP;
0269   using Base::stemIndex;
0270   using Base::theta;
0271   using Base::time;
0272   using Base::tipIndex;
0273   using Base::transverseMomentum;
0274 
0275   /// Return the number of track states associated to this track
0276   /// @note This is calculated by iterating over the track states which is
0277   ///       somewhat expensive. Consider caching this value if you need It
0278   ///       more than once.
0279   /// @return The number of track states
0280   unsigned int nTrackStates() const {
0281     // @TODO: This should probably be cached, distance is expensive
0282     //        without random access
0283     if (tipIndex() == kInvalid) {
0284       // no tip index -> no track states
0285       return 0;
0286     }
0287     auto tsRange = trackStatesReversed();
0288     return std::distance(tsRange.begin(), tsRange.end());
0289   }
0290 
0291   /// Return the index of this track in the track container
0292   /// @note This is separate from the tip index
0293   /// @return the track index
0294   IndexType index() const { return m_index; }
0295 
0296   /// @}
0297 
0298   /// @anchor track_proxy_track_states
0299   /// @name TrackProxy track state access
0300   /// Methods that give access to the track states of a track represented by @c TrackProxy.
0301   /// @{
0302 
0303   /// Return a const track state proxy to the outermost track state
0304   /// @return The outermost track state proxy
0305   ConstTrackStateProxy outermostTrackState() const {
0306     return m_container->trackStateContainer().getTrackState(tipIndex());
0307   }
0308 
0309   /// Return a mutable track state proxy to the outermost track state
0310   /// @return The outermost track state proxy
0311   TrackStateProxy outermostTrackState()
0312     requires(!ReadOnly)
0313   {
0314     return m_container->trackStateContainer().getTrackState(tipIndex());
0315   }
0316 
0317   /// Return a const track state proxy to the innermost track state
0318   /// @note This is only available, if the track is forward linked
0319   /// @return The innermost track state proxy
0320   auto innermostTrackState() const {
0321     using proxy_t = decltype(m_container->trackStateContainer().getTrackState(
0322         std::declval<IndexType>()));
0323 
0324     IndexType stem = component<IndexType, detail_tp::kStemIndexKey>();
0325     if (stem == kInvalid) {
0326       return std::optional<proxy_t>{};
0327     } else {
0328       return std::optional<proxy_t>{
0329           m_container->trackStateContainer().getTrackState(stem)};
0330     }
0331   }
0332 
0333   /// Return a mutable track state proxy to the innermost track state
0334   /// @note This is only available, if the track is forward linked
0335   /// @note Only available if the track proxy is not read-only
0336   /// @return The innermost track state proxy
0337   auto innermostTrackState()
0338     requires(!ReadOnly)
0339   {
0340     using proxy_t = decltype(m_container->trackStateContainer().getTrackState(
0341         std::declval<IndexType>()));
0342 
0343     IndexType stem = component<IndexType>(detail_tp::kStemIndexKey);
0344     if (stem == kInvalid) {
0345       return std::optional<proxy_t>{};
0346     } else {
0347       return std::optional<proxy_t>{
0348           m_container->trackStateContainer().getTrackState(stem)};
0349     }
0350   }
0351 
0352   /// Get a range over the track states of this track. Return value is
0353   /// compatible with range based for loop. Const version
0354   /// @note This range is from the outside inwards!
0355   /// @return Track state range to iterate over
0356   auto trackStatesReversed() const {
0357     return m_container->reverseTrackStateRange(m_index);
0358   }
0359 
0360   /// Get a range over the track states of this track. Return value is
0361   /// compatible with range based for loop. Mutable version
0362   /// @note Only available if the track proxy is not read-only
0363   /// @note This range is from the outside inwards!
0364   /// @return Track state range to iterate over
0365   auto trackStatesReversed()
0366     requires(!ReadOnly)
0367   {
0368     return m_container->reverseTrackStateRange(m_index);
0369   }
0370 
0371   /// Get a range over the track states of this track. Return value is
0372   /// compatible with range based for loop. This overload returns a const-only
0373   /// track state range, which means you cannot modify the track states obtained
0374   /// in the iteration.
0375   /// @note This range is from the inside out!
0376   /// @warning This access direction is only possible if the track states are
0377   ///          **forward-linked**.
0378   /// @return Track state range to iterate over
0379   auto trackStates() const {
0380     return m_container->forwardTrackStateRange(m_index);
0381   }
0382 
0383   /// Get a range over the track states of this track.
0384   /// Return value is compatible with range based for loop.
0385   /// This overload returns a mutable track state range, which means you
0386   /// can modify the track states obtained in the iteration.
0387   /// @note Only available if the track proxy is not read-only
0388   /// @note This range is from the inside out!
0389   /// @warning This access direction is only possible if the track states are
0390   ///          **forward-linked**.
0391   /// @return Track state range to iterate over
0392   auto trackStates()
0393     requires(!ReadOnly)
0394   {
0395     return m_container->forwardTrackStateRange(m_index);
0396   }
0397 
0398   /// @}
0399 
0400   /// @anchor track_proxy_track_state_manipulation
0401   /// @name TrackProxy track state manipulation
0402   /// Methods that manipulate the track states of a track represented by @c
0403   /// TrackProxy.
0404   ///
0405   /// **Copy Methods Overview:**
0406   ///
0407   /// Three main copy methods are available with different behaviors:
0408   /// - @c copyFrom(): Deep copy including all track states (creates new track
0409   ///                 states)
0410   /// - @c copyFromWithoutStates(): Copy only track properties, invalidate
0411   ///                               track state indices
0412   /// - @c copyFromShallow(): Shallow copy sharing the same track states (copy
0413   ///                         indices only)
0414   ///
0415   /// Choose based on your needs:
0416   /// - Use @c copyFrom() for independent track copies with separate track
0417   ///   states
0418   /// - Use @c copyFromWithoutStates() to update track metadata without
0419   ///   affecting trajectories
0420   /// - Use @c copyFromShallow() for lightweight copies when track states can
0421   ///   be shared
0422   /// @{
0423 
0424   /// Forward connect a track.
0425   /// This means setting indices from the inside out on all track states.
0426   /// @note Only available if the track proxy is not read-only
0427   void linkForward()
0428     requires(!ReadOnly)
0429   {
0430     IndexType last = kInvalid;
0431     for (auto ts : trackStatesReversed()) {
0432       ts.template component<IndexType>(detail_tp::kNextKey) = last;
0433       last = ts.index();
0434     }
0435     stemIndex() = last;
0436   }
0437 
0438   /// Append a track state to this track.
0439   /// This will modify the tip index to point at the newly created track state,
0440   /// which will be directly after the previous track state at tip index.
0441   /// @note Only available if the track proxy is not read-only
0442   /// @param mask The allocation prop mask for the new track state
0443   /// @return The newly added track state
0444   auto appendTrackState(TrackStatePropMask mask = TrackStatePropMask::All)
0445     requires(!ReadOnly)
0446   {
0447     auto& tsc = m_container->trackStateContainer();
0448     auto ts = tsc.makeTrackState(mask, tipIndex());
0449     tipIndex() = ts.index();
0450     return ts;
0451   }
0452 
0453   /// Create a complete deep copy of another track, including all track states.
0454   /// This creates new track states in the destination trajectory and copies
0455   /// all data from the source track states. The track state sequence order
0456   /// is preserved.
0457   ///
0458   /// **Implementation details:**
0459   /// - Track states are initially copied in reversed order for efficiency
0460   /// - The track state links are then updated using reverseTrackStates()
0461   /// - As a consequence, the resulting track is forward-linked
0462   ///
0463   /// **What gets copied:**
0464   /// - All track-level properties (parameters, covariance, particle hypothesis,
0465   ///   etc.)
0466   /// - Reference surface (shared pointer is copied)
0467   /// - Track summary data (nMeasurements, nHoles, chi2, etc.)
0468   /// - All dynamic track columns
0469   /// - Complete sequence of track states with all their data
0470   /// - All dynamic track state columns
0471   ///
0472   /// **Result:**
0473   /// - The destination track will have newly created track states
0474   /// - tipIndex() and stemIndex() will point to the new track
0475   /// states
0476   /// - Track state indices will be different from the source
0477   /// - All track state data will be identical to the source
0478   /// - The track will be forward-linked (stemIndex() will be valid)
0479   ///
0480   /// @note Only available if the track proxy is not read-only
0481   /// @note Both track containers must have compatible dynamic columns
0482   /// @tparam track_proxy_t the other track proxy's type
0483   /// @param other The source track proxy to copy from
0484   template <TrackProxyConcept track_proxy_t>
0485   void copyFrom(const track_proxy_t& other)
0486     requires(!ReadOnly)
0487   {
0488     copyFromWithoutStates(other);
0489 
0490     // append track states (cheap), but they're in the wrong order
0491     for (const auto& srcTrackState : other.trackStatesReversed()) {
0492       auto destTrackState = appendTrackState(srcTrackState.getMask());
0493       destTrackState.copyFrom(srcTrackState, Acts::TrackStatePropMask::All,
0494                               true);
0495     }
0496 
0497     // reverse using standard linked list reversal algorithm
0498     reverseTrackStates();
0499   }
0500 
0501   /// Copy track-level properties from another track, but not the track states.
0502   /// This copies all track metadata and properties but leaves the track state
0503   /// sequence unchanged. Useful when you want to copy track properties to an
0504   /// existing track that may already have track states.
0505   ///
0506   /// **What gets copied:**
0507   /// - Track parameters at reference surface
0508   /// - Covariance matrix at reference surface
0509   /// - Particle hypothesis
0510   /// - Reference surface (shared pointer is copied)
0511   /// - Track summary data (nMeasurements, nHoles, nOutliers, nSharedHits, chi2,
0512   /// nDoF)
0513   /// - All dynamic track columns
0514   ///
0515   /// **What does NOT get copied:**
0516   /// - Track states (existing track states remain unchanged in the container)
0517   ///
0518   /// **Result:**
0519   /// - All track-level properties are updated to match the source
0520   /// - tipIndex() and stemIndex() are set to kInvalid (track states
0521   /// become inaccessible)
0522   /// - Existing track states remain in the container but are no longer linked
0523   /// to this track
0524   /// - nTrackStates() will return 0 due to invalid indices
0525   ///
0526   /// @note Only available if the track proxy is not read-only
0527   /// @note Both track containers must have compatible dynamic columns
0528   /// @tparam track_proxy_t the other track proxy's type
0529   /// @param other The source track proxy to copy properties from
0530   template <TrackProxyConcept track_proxy_t>
0531   void copyFromWithoutStates(const track_proxy_t& other)
0532     requires(!ReadOnly)
0533   {
0534     setParticleHypothesis(other.particleHypothesis());
0535 
0536     if (other.hasReferenceSurface()) {
0537       setReferenceSurface(other.referenceSurface().getSharedPtr());
0538       parameters() = other.parameters();
0539       covariance() = other.covariance();
0540     } else {
0541       setReferenceSurface(nullptr);
0542     }
0543 
0544     nMeasurements() = other.nMeasurements();
0545     nHoles() = other.nHoles();
0546     nOutliers() = other.nOutliers();
0547     nSharedHits() = other.nSharedHits();
0548     chi2() = other.chi2();
0549     nDoF() = other.nDoF();
0550 
0551     m_container->copyDynamicFrom(m_index, other.m_container->container(),
0552                                  other.m_index);
0553 
0554     tipIndex() = kInvalid;
0555     stemIndex() = kInvalid;
0556   }
0557 
0558   /// Create a shallow copy from another track, sharing the same track states.
0559   /// This copies all track-level properties and makes the destination track
0560   /// point to the same track state sequence as the source. The track states
0561   /// themselves are not duplicated - both tracks will reference the same
0562   /// track state objects in memory.
0563   ///
0564   /// **What gets copied:**
0565   /// - All track-level properties (parameters, covariance, particle hypothesis,
0566   /// etc.)
0567   /// - Reference surface (shared pointer is copied)
0568   /// - Track summary data (nMeasurements, nHoles, chi2, etc.)
0569   /// - All dynamic track columns
0570   /// - tipIndex() and stemIndex() (track state linking information)
0571   ///
0572   /// **What gets shared (not duplicated):**
0573   /// - Track states (both tracks reference the same track state objects)
0574   ///
0575   /// **Result:**
0576   /// - The destination track will have the same nTrackStates() as the source
0577   /// - Both tracks will iterate over the same track state sequence
0578   /// - Modifications to track states will be visible in both tracks
0579   /// - Track state indices will be identical between tracks
0580   /// - The destination track will have a different track index than the source
0581   ///
0582   /// @warning Modifying track states through either track will affect both tracks
0583   ///          since they share the same track state objects
0584   /// @warning It is the user's responsibility to ensure that the tip and stem
0585   ///          indices from the source track are valid in the destination
0586   ///          track's track state container. No validation is performed -
0587   ///          invalid indices will lead to undefined behavior when accessing
0588   ///          track states
0589   /// @note Only available if the track proxy is not read-only
0590   /// @note Both track containers must have compatible dynamic columns
0591   /// @tparam track_proxy_t the other track proxy's type
0592   /// @param other The source track proxy to create a shallow copy from
0593   template <TrackProxyConcept track_proxy_t>
0594   void copyFromShallow(const track_proxy_t& other)
0595     requires(!ReadOnly)
0596   {
0597     copyFromWithoutStates(other);
0598     tipIndex() = other.tipIndex();
0599     stemIndex() = other.stemIndex();
0600   }
0601 
0602   /// Reverse the ordering of track states for this track
0603   /// Afterwards, the previous endpoint of the track state sequence will be
0604   /// the "innermost" track state
0605   /// @note Only available if the track proxy is not read-only
0606   /// @note This is dangerous with branching track state sequences, as it will break them
0607   /// @note This also automatically forward-links the track!
0608   /// @param invertJacobians Whether to invert the Jacobians of the track states
0609   void reverseTrackStates(bool invertJacobians = false)
0610     requires(!ReadOnly)
0611   {
0612     IndexType current = tipIndex();
0613     IndexType next = kInvalid;
0614     IndexType prev = kInvalid;
0615 
0616     stemIndex() = tipIndex();
0617 
0618     // @TODO: Maybe refactor to not need this variable if invertJacobians == false
0619     BoundMatrix nextJacobian;
0620 
0621     while (current != kInvalid) {
0622       auto ts = m_container->trackStateContainer().getTrackState(current);
0623       prev = ts.previous();
0624       ts.template component<IndexType>(detail_tp::kNextKey) = prev;
0625       ts.previous() = next;
0626       if (invertJacobians) {
0627         if (next != kInvalid) {
0628           BoundMatrix curJacobian = ts.jacobian();
0629           ts.jacobian() = nextJacobian.inverse();
0630           nextJacobian = curJacobian;
0631         } else {
0632           nextJacobian = ts.jacobian();
0633           ts.jacobian().setZero();
0634         }
0635       }
0636       next = current;
0637       tipIndex() = current;
0638       current = prev;
0639     }
0640   }
0641 
0642   /// @}
0643 
0644   /// @anchor track_proxy_generic_component
0645   /// @name TrackProxy generic component access
0646   /// Methods that give access to generic components of a track represented by
0647   /// @c TrackProxy.  Internally, a compile-time hash of the component name is
0648   /// used to identify which component is being requested. Most of the named
0649   /// methods in @ref track_proxy_props "TrackProxy properties" use these
0650   /// methods to retrieve the actual data.
0651   ///
0652   /// A number of overloads exist, where you can either supply the
0653   /// @ref HashedString @c key as a template parameter or a runtime argument.  The
0654   /// former has the advantage of being guaranteed to be evaluated at
0655   /// compile-time.
0656   ///
0657   /// @{
0658 
0659   /// Retrieve a mutable reference to a component
0660   /// @tparam T The type of the component to access
0661   /// @tparam key String key for the component to access
0662   /// @return Mutable reference to the component given by @p key
0663   template <typename T, HashedString key>
0664   constexpr T& component()
0665     requires(!ReadOnly)
0666   {
0667     return m_container->template component<T, key>(m_index);
0668   }
0669 
0670   /// Retrieve a mutable reference to a component
0671   /// @tparam T The type of the component to access
0672   /// @param key String key for the component to access
0673   /// @return Mutable reference to the component given by @p key
0674   template <typename T>
0675   constexpr T& component(HashedString key)
0676     requires(!ReadOnly)
0677   {
0678     return m_container->template component<T>(key, m_index);
0679   }
0680 
0681   /// Retrieve a mutable reference to a component
0682   /// @tparam T The type of the component to access
0683   /// @param key String key for the component to access
0684   /// @note This might hash the @p key at runtime instead of compile-time
0685   /// @return Mutable reference to the component given by @p key
0686   template <typename T>
0687   constexpr T& component(std::string_view key)
0688     requires(!ReadOnly)
0689   {
0690     return m_container->template component<T>(hashStringDynamic(key), m_index);
0691   }
0692 
0693   /// Retrieve a const reference to a component
0694   /// @tparam T The type of the component to access
0695   /// @tparam key String key for the component to access
0696   /// @return Const reference to the component given by @p key
0697   template <typename T, HashedString key>
0698   constexpr const T& component() const {
0699     return m_container->template component<T, key>(m_index);
0700   }
0701 
0702   /// Check whether a dynamic column exists
0703   /// @param key String key for the component to check
0704   /// @return whether the column exists
0705   bool hasColumn(HashedString key) const { return m_container->hasColumn(key); }
0706 
0707   /// Retrieve a const reference to a component
0708   /// @tparam T The type of the component to access
0709   /// @param key String key for the component to access
0710   /// @return Const reference to the component given by @p key
0711   template <typename T>
0712   constexpr const T& component(HashedString key) const {
0713     return m_container->template component<T>(key, m_index);
0714   }
0715 
0716   /// Retrieve a const reference to a component
0717   /// @tparam T The type of the component to access
0718   /// @param key String key for the component to access
0719   /// @note This might hash the @p key at runtime instead of compile-time
0720   /// @return Const reference to the component given by @p key
0721   template <typename T>
0722   constexpr const T& component(std::string_view key) const {
0723     return m_container->template component<T>(hashStringDynamic(key), m_index);
0724   }
0725 
0726   /// @}
0727 
0728   /// Return the track parameters at the reference surface
0729   /// @note The parameters are created on the fly
0730   /// @return the track parameters
0731   BoundTrackParameters createParametersAtReference() const {
0732     return BoundTrackParameters(referenceSurface().getSharedPtr(), parameters(),
0733                                 covariance(), particleHypothesis());
0734   }
0735 
0736   /// Convert a track state into track parameters
0737   /// @note The parameters are created on the fly
0738   /// @param trackState Track state to convert to parameters
0739   /// @return the track parameters
0740   BoundTrackParameters createParametersFromState(
0741       const ConstTrackStateProxy& trackState) const {
0742     return BoundTrackParameters(trackState.referenceSurface().getSharedPtr(),
0743                                 trackState.parameters(),
0744                                 trackState.covariance(), particleHypothesis());
0745   }
0746 
0747   /// Return a reference to the track container backend, mutable version.
0748   /// @note Only available if the track proxy is not read-only
0749   /// @return reference to the track container backend
0750   auto& container()
0751     requires(!ReadOnly)
0752   {
0753     return *m_container;
0754   }
0755 
0756   /// Return a reference to the track container backend, const version.
0757   /// @return reference to the track container backend
0758   const auto& container() const { return *m_container; }
0759 
0760  private:
0761   TrackProxy(
0762       const_if_t<ReadOnly, TrackContainer<Container, Trajectory, holder_t>>&
0763           container,
0764       IndexType itrack)
0765       : m_container{&container}, m_index{itrack} {}
0766 
0767   detail_lt::TransitiveConstPointer<
0768       const_if_t<ReadOnly, TrackContainer<Container, Trajectory, holder_t>>>
0769       m_container;
0770   IndexType m_index;
0771 };
0772 
0773 }  // namespace Acts