Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:10:00

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2023 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 http://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/Definitions/TrackParametrization.hpp"
0012 #include "Acts/EventData/MultiTrajectory.hpp"
0013 #include "Acts/EventData/ParticleHypothesis.hpp"
0014 #include "Acts/EventData/TrackContainerBackendConcept.hpp"
0015 #include "Acts/EventData/TrackParameters.hpp"
0016 #include "Acts/EventData/TrackStatePropMask.hpp"
0017 #include "Acts/Utilities/Concepts.hpp"
0018 #include "Acts/Utilities/HashedString.hpp"
0019 #include "Acts/Utilities/UnitVectors.hpp"
0020 
0021 #include <iterator>
0022 #include <type_traits>
0023 
0024 namespace Acts {
0025 
0026 template <ACTS_CONCEPT(Acts::TrackContainerBackend) track_container_t,
0027           typename traj_t, template <typename> class holder_t>
0028 class TrackContainer;
0029 
0030 namespace detail_tc {
0031 template <typename T, bool select>
0032 using ConstIf = std::conditional_t<select, const T, T>;
0033 
0034 /// Helper iterator to allow iteration over tracks via track proxies.
0035 template <typename container_t, typename proxy_t, bool ReadOnly>
0036 class TrackProxyIterator {
0037   using ProxyType = proxy_t;
0038   using IndexType = typename ProxyType::IndexType;
0039   using ContainerType = container_t;
0040 
0041  public:
0042   using iterator_category = std::random_access_iterator_tag;
0043   using value_type = ProxyType;
0044   using difference_type = std::ptrdiff_t;
0045   using pointer = void;
0046   using reference = void;
0047 
0048   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0049   TrackProxyIterator(container_t& container, IndexType itrack)
0050       : m_container(&container), m_itrack(itrack) {}
0051 
0052   template <bool RO = ReadOnly, typename = std::enable_if_t<RO>>
0053   TrackProxyIterator(const container_t& container, IndexType itrack)
0054       : m_container(&container), m_itrack(itrack) {}
0055 
0056   TrackProxyIterator& operator++() {
0057     m_itrack++;
0058     return *this;
0059   }
0060   TrackProxyIterator& operator--() {
0061     m_itrack--;
0062     return *this;
0063   }
0064 
0065   bool operator==(const TrackProxyIterator& other) const {
0066     return m_container == other.m_container && m_itrack == other.m_itrack;
0067   }
0068 
0069   bool operator!=(const TrackProxyIterator& other) const {
0070     return !(*this == other);
0071   }
0072 
0073   bool operator<(const TrackProxyIterator& other) const {
0074     return m_itrack < other.m_itrack;
0075   }
0076 
0077   bool operator>(const TrackProxyIterator& other) const {
0078     return m_itrack > other.m_itrack;
0079   }
0080 
0081   bool operator<=(const TrackProxyIterator& other) const {
0082     return m_itrack <= other.m_itrack;
0083   }
0084 
0085   bool operator>=(const TrackProxyIterator& other) const {
0086     return m_itrack >= other.m_itrack;
0087   }
0088 
0089   ProxyType operator*() const { return m_container->getTrack(m_itrack); }
0090 
0091   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0092   ProxyType operator*() {
0093     return m_container->getTrack(m_itrack);
0094   }
0095 
0096   TrackProxyIterator operator[](difference_type n) const {
0097     TrackProxyIterator copy = *this;
0098     copy += n;
0099     return copy;
0100   };
0101 
0102   TrackProxyIterator& operator+=(difference_type n) {
0103     m_itrack += n;
0104     return *this;
0105   }
0106 
0107   TrackProxyIterator operator-=(difference_type n) {
0108     m_itrack -= n;
0109     return *this;
0110   }
0111 
0112   friend difference_type operator-(const TrackProxyIterator& lhs,
0113                                    const TrackProxyIterator& rhs) {
0114     return lhs.m_itrack - rhs.m_itrack;
0115   }
0116 
0117   friend TrackProxyIterator operator+(const TrackProxyIterator& lhs,
0118                                       difference_type rhs) {
0119     TrackProxyIterator copy = lhs;
0120     copy += rhs;
0121     return copy;
0122   }
0123 
0124   friend TrackProxyIterator operator+(difference_type lhs,
0125                                       const TrackProxyIterator& rhs) {
0126     return rhs + lhs;
0127   }
0128 
0129   friend TrackProxyIterator operator-(const TrackProxyIterator& lhs,
0130                                       difference_type rhs) {
0131     return lhs + (-rhs);
0132   }
0133 
0134   friend TrackProxyIterator operator-(difference_type lhs,
0135                                       const TrackProxyIterator& rhs) {
0136     return rhs + (-lhs);
0137   }
0138 
0139  private:
0140   detail_lt::TransitiveConstPointer<ConstIf<ContainerType, ReadOnly>>
0141       m_container;
0142   IndexType m_itrack;
0143 };
0144 
0145 }  // namespace detail_tc
0146 
0147 /// Proxy class representing a single track.
0148 /// This class provides a **view** into an associated @ref TrackContainer, and
0149 /// has **reference semantics**. You can think of it as a pointer to a vector
0150 /// of tracks, which exposes an object-oriented interface for accessing the
0151 /// track properties.
0152 ///
0153 /// @tparam track_container_t the container backend
0154 /// @tparam trajectory_t the track state container backend
0155 /// @tparam holder_t ownership management class for the backend
0156 /// @tparam read_only true if this track container is not mutable
0157 template <typename track_container_t, typename trajectory_t,
0158           template <typename> class holder_t, bool read_only = true>
0159 class TrackProxy {
0160  public:
0161   /// Indicates whether this track proxy is read-only or if it can be modified
0162   static constexpr bool ReadOnly = read_only;
0163 
0164   /// The track container backend given as a template parameter
0165   using Container = track_container_t;
0166 
0167   /// The track state container backend given as a template parameter
0168   using Trajectory = trajectory_t;
0169 
0170   /// The index type of the track container
0171   using IndexType = typename Container::IndexType;
0172 
0173   /// Sentinel value that indicates an invalid index
0174   static constexpr IndexType kInvalid = Container::kInvalid;
0175 
0176   /// Alias for the mutable version of this track proxy, with the same backends
0177   using MutableTrackProxy =
0178       TrackProxy<track_container_t, trajectory_t, holder_t, false>;
0179 
0180   /// Alias for the const version of this track proxy, with the same backends
0181   using ConstTrackProxy =
0182       TrackProxy<track_container_t, trajectory_t, holder_t, true>;
0183 
0184   /// Alias for an associated const track proxy, with the same backends
0185   using ConstProxyType = ConstTrackProxy;
0186 
0187   /// Alias for an associated mutable track state proxy, with the same backends
0188   using TrackStateProxy = typename Trajectory::TrackStateProxy;
0189 
0190   /// Alias for an associated const track state proxy, with the same backends
0191   using ConstTrackStateProxy = typename Trajectory::ConstTrackStateProxy;
0192 
0193   /// Map-type for a bound parameter vector. This has reference semantics, i.e.
0194   /// points at a matrix by an internal pointer.
0195   using Parameters =
0196       typename detail_lt::Types<eBoundSize, false>::CoefficientsMap;
0197 
0198   /// Same as @ref Parameters, but with const semantics
0199   using ConstParameters =
0200       typename detail_lt::Types<eBoundSize, true>::CoefficientsMap;
0201 
0202   /// Map-type for a bound covariance. This has reference semantics, i.e.
0203   /// points at a matrix by an internal pointer.
0204   using Covariance =
0205       typename detail_lt::Types<eBoundSize, false>::CovarianceMap;
0206 
0207   /// Same as @ref Covariance, but with const semantics
0208   using ConstCovariance =
0209       typename detail_lt::Types<eBoundSize, true>::CovarianceMap;
0210 
0211 #ifndef DOXYGEN
0212   friend TrackContainer<Container, Trajectory, holder_t>;
0213   friend MutableTrackProxy;
0214   friend ConstTrackProxy;
0215   // Track proxies are friends, not food!
0216   template <typename A, typename B, template <typename> class H, bool R>
0217   friend class TrackProxy;
0218 #endif
0219 
0220   /// @anchor track_proxy_construct
0221   /// @name Constructors and assignment operator
0222   ///
0223   /// Public constructors and assignment operators for @c TrackProxy only
0224   /// allow construction from another @c TrackProxy. You should generally
0225   /// not have to construct @c TrackProxy manually.
0226   ///
0227   /// @{
0228 
0229   /// Copy constructor from a mutable track proxy. This is always valid, either
0230   /// mutable to mutable or mutable to const
0231   /// @param other the other track state proxy
0232   TrackProxy(const MutableTrackProxy& other)
0233       : m_container{other.m_container}, m_index{other.m_index} {}
0234 
0235   /// Copy assignment operator from mutable track proxy. This is always valid,
0236   /// either mutable to mutable or mutable to const
0237   /// @param other the other track state proxy
0238   TrackProxy& operator=(const MutableTrackProxy& other) {
0239     m_container = other.m_container;
0240     m_index = other.m_index;
0241     return *this;
0242   }
0243 
0244   /// @}
0245 
0246   /// Equality operator with another track proxy
0247   /// Checks the container identity and the track index
0248   /// @return True if the track proxies refer to the same track
0249   bool operator==(const TrackProxy& other) const {
0250     return &(*m_container) == &(*other.m_container) && m_index == other.m_index;
0251   }
0252 
0253   /// @anchor track_proxy_props
0254   /// @name TrackProxy properties
0255   /// Methods that give access to the properties of a track represented by
0256   /// @c TrackProxy.
0257   ///
0258   /// Many of these methods come in a @c const and a non-@c const version. The
0259   /// non-@c const version is only available if you have an instance of
0260   /// @c TrackProxy that does not have the @c read_only template parameter set to
0261   /// @c true, even if you hold it as an lvalue.
0262   ///
0263   /// @{
0264 
0265   /// Get the tip index, i.e. the entry point into the track state container
0266   /// @return the tip index by value
0267   IndexType tipIndex() const {
0268     return component<IndexType>(hashString("tipIndex"));
0269   }
0270 
0271   /// Index of the stem, i.e. the innermost track state of the track.
0272   /// This might be invalid, signifying that the track state is not
0273   /// forward-linked.
0274   /// @return the stem index
0275   IndexType stemIndex() const {
0276     return component<IndexType>(hashString("stemIndex"));
0277   }
0278 
0279   /// Get a mutable reference to the tip index, i.e. the entry point into the
0280   /// track container
0281   /// @note Only available if the track proxy is not read-only
0282   /// @return mutable reference to the tip index
0283   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0284   IndexType& tipIndex() {
0285     return component<IndexType>(hashString("tipIndex"));
0286   }
0287 
0288   /// Index of the stem, i.e. the innermost track state of the track.
0289   /// This might be invalid, signifying that the track state is not
0290   /// forward-linked.
0291   /// @note Only available if the track proxy is not read-only
0292   /// @return mutable reference to the stem index
0293   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0294   IndexType& stemIndex() {
0295     return component<IndexType>(hashString("stemIndex"));
0296   }
0297 
0298   /// Get the reference surface of the track (e.g. the perigee)
0299   /// @return the reference surface
0300   const Surface& referenceSurface() const {
0301     return *m_container->container().referenceSurface_impl(m_index);
0302   }
0303 
0304   // NOLINTBEGIN(performance-unnecessary-value-param)
0305   // looks like a false-positive. clang-tidy believes `srf` is not movable.
0306   /// Set a new reference surface for this track
0307   /// @param srf The surface to set
0308   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0309   void setReferenceSurface(std::shared_ptr<const Surface> srf) {
0310     m_container->container().setReferenceSurface_impl(m_index, std::move(srf));
0311   }
0312   // NOLINTEND(performance-unnecessary-value-param)
0313 
0314   /// Returns whether the track has a reference surface or not
0315   /// @return whether a surface exists or not
0316   bool hasReferenceSurface() const {
0317     // @TODO: This could be more efficient
0318     return m_container->container().referenceSurface_impl(m_index) != nullptr;
0319   }
0320 
0321   /// Get the parameters of the track at the reference surface (e.g. perigee).
0322   /// Const version
0323   /// @return Proxy vector for the parameters
0324   ConstParameters parameters() const {
0325     return m_container->parameters(m_index);
0326   }
0327 
0328   /// Get the covariance of the track at the reference surface (e.g. perigee).
0329   /// Const version
0330   /// @return Proxy matrix for the covariance
0331   ConstCovariance covariance() const {
0332     return m_container->covariance(m_index);
0333   }
0334 
0335   /// Get the parameters of the track at the reference surface (e.g. perigee).
0336   /// Mutable version
0337   /// @note Only available if the track proxy is not read-only
0338   /// @return Proxy vector for the parameters
0339   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0340   Parameters parameters() {
0341     return m_container->parameters(m_index);
0342   }
0343 
0344   /// Get the covariance of the track at the reference surface (e.g. perigee).
0345   /// Mutable version
0346   /// @note Only available if the track proxy is not read-only
0347   /// @return Proxy matrix for the covariance
0348   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0349   Covariance covariance() {
0350     return m_container->covariance(m_index);
0351   }
0352 
0353   /// Access the theta parameter of the track at the reference surface
0354   /// @return The theta parameter
0355   ActsScalar theta() const {
0356     return parameters()[eBoundTheta];
0357   }
0358 
0359   /// Access the phi parameter of the track at the reference surface
0360   /// @return The phi parameter
0361   ActsScalar phi() const {
0362     return parameters()[eBoundPhi];
0363   }
0364 
0365   /// Access the loc0 parameter of the track at the reference surface
0366   /// @return The loc0 parameter
0367   ActsScalar loc0() const {
0368     return parameters()[eBoundLoc0];
0369   }
0370 
0371   /// Access the loc1 parameter of the track at the reference surface
0372   /// @return The loc1 parameter
0373   ActsScalar loc1() const {
0374     return parameters()[eBoundLoc1];
0375   }
0376 
0377   /// Access the time parameter of the track at the reference surface
0378   /// @return The time parameter
0379   ActsScalar time() const {
0380     return parameters()[eBoundTime];
0381   }
0382 
0383   /// Access the q/p (curvature) parameter of the track at the reference surface
0384   /// @return The q/p parameter
0385   ActsScalar qOverP() const {
0386     return parameters()[eBoundQOverP];
0387   }
0388 
0389   /// Get the particle hypothesis
0390   /// @return the particle hypothesis
0391   ParticleHypothesis particleHypothesis() const {
0392     return m_container->container().particleHypothesis_impl(m_index);
0393   }
0394 
0395   /// Set a new particle hypothesis for this track
0396   /// @note Only available if the track proxy is not read-only
0397   /// @param particleHypothesis The particle hypothesis to set
0398   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0399   void setParticleHypothesis(const ParticleHypothesis& particleHypothesis) {
0400     m_container->container().setParticleHypothesis_impl(m_index,
0401                                                         particleHypothesis);
0402   }
0403 
0404   /// Get the charge of the tack
0405   /// @note this depends on the charge hypothesis
0406   /// @return The absolute track momentum
0407   ActsScalar charge() const {
0408     return particleHypothesis().qFromQOP(qOverP());
0409   }
0410 
0411   /// Get the absolute momentum of the tack
0412   /// @return The absolute track momentum
0413   ActsScalar absoluteMomentum() const {
0414     return particleHypothesis().extractMomentum(qOverP());
0415   }
0416 
0417   /// Get the transverse momentum of the track
0418   /// @return The track transverse momentum value
0419   ActsScalar transverseMomentum() const {
0420     return std::sin(theta()) * absoluteMomentum();
0421   }
0422 
0423   /// Get a unit vector along the track direction at the reference surface
0424   /// @return The direction unit vector
0425   Vector3 direction() const {
0426     return makeDirectionFromPhiTheta(phi(), theta());
0427   }
0428 
0429   /// Get the global momentum vector
0430   /// @return the global momentum vector
0431   Vector3 momentum() const {
0432     return absoluteMomentum() * direction();
0433   }
0434 
0435   /// Return the number of track states associated to this track
0436   /// @note This is calculated by iterating over the track states which is
0437   ///       somewhat expensive. Consider caching this value if you need It
0438   ///       more than once.
0439   /// @return The number of track states
0440   unsigned int nTrackStates() const {
0441     // @TODO: This should probably be cached, distance is expensive
0442     //        without random access
0443     if (tipIndex() == kInvalid) {
0444       // no tip index -> no track states
0445       return 0;
0446     }
0447     auto tsRange = trackStatesReversed();
0448     return std::distance(tsRange.begin(), tsRange.end());
0449   }
0450 
0451   /// Return the number of measurements for the track. Const version
0452   /// @note Only available if the track proxy is not read-only
0453   /// @return The number of measurements
0454   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0455   unsigned int& nMeasurements() {
0456     return component<unsigned int, hashString("nMeasurements")>();
0457   }
0458 
0459   /// Return a mutable reference to the number of measurements for the track.
0460   /// Mutable version
0461   /// @return The number of measurements
0462   unsigned int nMeasurements() const {
0463     return component<unsigned int, hashString("nMeasurements")>();
0464   }
0465 
0466   /// Return a mutable reference to the number of holes for the track.
0467   /// Mutable version
0468   /// @note Only available if the track proxy is not read-only
0469   /// @return The number of holes
0470   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0471   unsigned int& nHoles() {
0472     return component<unsigned int, hashString("nHoles")>();
0473   }
0474 
0475   /// Return the number of measurements for the track. Const version
0476   /// @return The number of measurements
0477   unsigned int nHoles() const {
0478     return component<unsigned int, hashString("nHoles")>();
0479   }
0480 
0481   /// Return a mutable reference to the number of outliers for the track.
0482   /// Mutable version
0483   /// @note Only available if the track proxy is not read-only
0484   /// @return The number of outliers
0485   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0486   unsigned int& nOutliers() {
0487     return component<unsigned int, hashString("nOutliers")>();
0488   }
0489 
0490   /// Return the number of outliers for the track. Const version
0491   /// @return The number of outliers
0492   unsigned int nOutliers() const {
0493     return component<unsigned int, hashString("nOutliers")>();
0494   }
0495 
0496   /// Return a mutable reference to the number of shared hits for the track.
0497   /// Mutable version
0498   /// @note Only available if the track proxy is not read-only
0499   /// @return The number of shared hits
0500   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0501   unsigned int& nSharedHits() {
0502     return component<unsigned int, hashString("nSharedHits")>();
0503   }
0504 
0505   /// Return the number of shared hits for the track. Const version
0506   /// @return The number of shared hits
0507   unsigned int nSharedHits() const {
0508     return component<unsigned int, hashString("nSharedHits")>();
0509   }
0510 
0511   /// Return a mutable reference to the chi squared
0512   /// Mutable version
0513   /// @note Only available if the track proxy is not read-only
0514   /// @return The chi squared
0515   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0516   float& chi2() {
0517     return component<float, hashString("chi2")>();
0518   }
0519 
0520   /// Return the chi squared for the track. Const version
0521   /// @return The chi squared
0522   float chi2() const {
0523     return component<float, hashString("chi2")>();
0524   }
0525 
0526   /// Return a mutable reference to the number of degrees of freedom for the
0527   /// track. Mutable version
0528   /// @note Only available if the track proxy is not read-only
0529   /// @return The number of degrees of freedom
0530   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0531   unsigned int& nDoF() {
0532     return component<unsigned int, hashString("ndf")>();
0533   }
0534 
0535   /// Return the number of degrees of freedom for the track. Const version
0536   /// @return The number of degrees of freedom
0537   unsigned int nDoF() const {
0538     return component<unsigned int, hashString("ndf")>();
0539   }
0540 
0541   /// Return the index of this track in the track container
0542   /// @note This is separate from the tip index
0543   /// @return the track index
0544   IndexType index() const {
0545     return m_index;
0546   }
0547 
0548   /// @}
0549 
0550   /// @anchor track_proxy_track_states
0551   /// @name TrackProxy track state access
0552   /// Methods that give access to the track states of a track represented by @c TrackProxy.
0553   /// @{
0554 
0555   /// Return a const track state proxy to the innermost track state
0556   /// @note This is only available, if the track is forward linked
0557   /// @return The innermost track state proxy
0558   auto innermostTrackState() const {
0559     using proxy_t = decltype(m_container->trackStateContainer().getTrackState(
0560         std::declval<IndexType>()));
0561 
0562     IndexType stem = component<IndexType, hashString("stemIndex")>();
0563     if (stem == kInvalid) {
0564       return std::optional<proxy_t>{};
0565     } else {
0566       return std::optional<proxy_t>{
0567           m_container->trackStateContainer().getTrackState(stem)};
0568     }
0569   }
0570 
0571   /// Return a mutable track state proxy to the innermost track state
0572   /// @note This is only available, if the track is forward linked
0573   /// @note Only available if the track proxy is not read-only
0574   /// @return The innermost track state proxy
0575   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0576   auto innermostTrackState() {
0577     using proxy_t = decltype(m_container->trackStateContainer().getTrackState(
0578         std::declval<IndexType>()));
0579 
0580     IndexType stem = component<IndexType>(hashString("stemIndex"));
0581     if (stem == kInvalid) {
0582       return std::optional<proxy_t>{};
0583     } else {
0584       return std::optional<proxy_t>{
0585           m_container->trackStateContainer().getTrackState(stem)};
0586     }
0587   }
0588 
0589   /// Get a range over the track states of this track. Return value is
0590   /// compatible with range based for loop. Const version
0591   /// @note This range is from the outside inwards!
0592   /// @return Track state range to iterate over
0593   auto trackStatesReversed() const {
0594     return m_container->reverseTrackStateRange(m_index);
0595   }
0596 
0597   /// Get a range over the track states of this track. Return value is
0598   /// compatible with range based for loop. Mutable version
0599   /// @note Only available if the track proxy is not read-only
0600   /// @note This range is from the outside inwards!
0601   /// @return Track state range to iterate over
0602   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0603   auto trackStatesReversed() {
0604     return m_container->reverseTrackStateRange(m_index);
0605   }
0606 
0607   /// Get a range over the track states of this track. Return value is
0608   /// compatible with range based for loop. This overload returns a const-only
0609   /// track state range, which means you cannot modify the track states obtained
0610   /// in the iteration.
0611   /// @note This range is from the inside out!
0612   /// @warning This access direction is only possible if the track states are
0613   ///          **forward-linked**.
0614   /// @return Track state range to iterate over
0615   auto trackStates() const {
0616     return m_container->forwardTrackStateRange(m_index);
0617   }
0618 
0619   /// Get a range over the track states of this track.
0620   /// Return value is compatible with range based for loop.
0621   /// This overload returns a mutable track state range, which means you
0622   /// can modify the track states obtained in the iteration.
0623   /// @note Only available if the track proxy is not read-only
0624   /// @note This range is from the inside out!
0625   /// @warning This access direction is only possible if the track states are
0626   ///          **forward-linked**.
0627   /// @return Track state range to iterate over
0628   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0629   auto trackStates() {
0630     return m_container->forwardTrackStateRange(m_index);
0631   }
0632 
0633   /// @}
0634 
0635   /// @anchor track_proxy_track_state_manipulation
0636   /// @name TrackProxy track state manipulation
0637   /// Methods that manipulate the track states of a track represented by @c TrackProxy.
0638   /// @{
0639 
0640   /// Forward connect a track.
0641   /// This means setting indices from the inside out on all track states.
0642   /// @note Only available if the track proxy is not read-only
0643   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0644   void linkForward() {
0645     IndexType last = kInvalid;
0646     for (auto ts : trackStatesReversed()) {
0647       ts.template component<IndexType>(hashString("next")) = last;
0648       last = ts.index();
0649     }
0650     stemIndex() = last;
0651   }
0652 
0653   /// Append a track state to this track.
0654   /// This will modify the tip index to point at the newly created track state,
0655   /// which will be directly after the previous track state at tip index.
0656   /// @note Only available if the track proxy is not read-only
0657   /// @param mask The allocation prop mask for the new track state
0658   /// @return The newly added track state
0659   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0660   auto appendTrackState(TrackStatePropMask mask = TrackStatePropMask::All) {
0661     auto& tsc = m_container->trackStateContainer();
0662     auto ts = tsc.makeTrackState(mask, tipIndex());
0663     tipIndex() = ts.index();
0664     return ts;
0665   }
0666 
0667   /// Copy the content of another track proxy into this one
0668   /// @note Only available if the track proxy is not read-only
0669   /// @tparam track_proxy_t the other track proxy's type
0670   /// @param other The track proxy
0671   /// @param copyTrackStates Copy the track state sequence from @p other
0672   template <typename track_proxy_t, bool RO = ReadOnly,
0673             typename = std::enable_if_t<!RO>>
0674   void copyFrom(const track_proxy_t& other, bool copyTrackStates = true) {
0675     // @TODO: Add constraint on which track proxies are allowed,
0676     // this is only implicit right now
0677 
0678     if (copyTrackStates) {
0679       // append track states (cheap), but they're in the wrong order
0680       for (const auto& srcTrackState : other.trackStatesReversed()) {
0681         auto destTrackState = appendTrackState(srcTrackState.getMask());
0682         if (srcTrackState.hasCalibrated()) {
0683           destTrackState.allocateCalibrated(srcTrackState.calibratedSize());
0684         }
0685         destTrackState.copyFrom(srcTrackState, Acts::TrackStatePropMask::All,
0686                                 true);
0687       }
0688 
0689       // reverse using standard linked list reversal algorithm
0690       reverseTrackStates();
0691     }
0692 
0693     parameters() = other.parameters();
0694     covariance() = other.covariance();
0695     setParticleHypothesis(other.particleHypothesis());
0696     if (other.hasReferenceSurface()) {
0697       setReferenceSurface(other.referenceSurface().getSharedPtr());
0698     }
0699     nMeasurements() = other.nMeasurements();
0700     nHoles() = other.nHoles();
0701     nOutliers() = other.nOutliers();
0702     nSharedHits() = other.nSharedHits();
0703     chi2() = other.chi2();
0704     nDoF() = other.nDoF();
0705 
0706     m_container->copyDynamicFrom(m_index, other.m_container->container(),
0707                                  other.m_index);
0708   }
0709 
0710   /// Reverse the ordering of track states for this track
0711   /// Afterwards, the previous endpoint of the track state sequence will be the
0712   /// "innermost" track state
0713   /// @note Only available if the track proxy is not read-only
0714   /// @note This is dangerous with branching track state sequences, as it will break them
0715   /// @note This also automatically forward-links the track!
0716   /// @param invertJacobians Whether to invert the Jacobians of the track states
0717   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0718   void reverseTrackStates(bool invertJacobians = false) {
0719     IndexType current = tipIndex();
0720     IndexType next = kInvalid;
0721     IndexType prev = kInvalid;
0722 
0723     stemIndex() = tipIndex();
0724 
0725     // @TODO: Maybe refactor to not need this variable if invertJacobians == false
0726     BoundMatrix nextJacobian;
0727 
0728     while (current != kInvalid) {
0729       auto ts = m_container->trackStateContainer().getTrackState(current);
0730       prev = ts.previous();
0731       ts.template component<IndexType>(hashString("next")) = prev;
0732       ts.previous() = next;
0733       if (invertJacobians) {
0734         if (next != kInvalid) {
0735           BoundMatrix curJacobian = ts.jacobian();
0736           ts.jacobian() = nextJacobian.inverse();
0737           nextJacobian = curJacobian;
0738         } else {
0739           nextJacobian = ts.jacobian();
0740           ts.jacobian().setZero();
0741         }
0742       }
0743       next = current;
0744       tipIndex() = current;
0745       current = prev;
0746     }
0747   }
0748 
0749   /// @}
0750 
0751   /// @anchor track_proxy_generic_component
0752   /// @name TrackProxy generic component access
0753   /// Methods that give access to generic components of a track represented by
0754   /// @c TrackProxy.  Internally, a compile-time hash of the component name is
0755   /// used to identify which component is being requested. Most of the named
0756   /// methods in @ref track_proxy_props "TrackProxy properties" use these
0757   /// methods to retrieve the actual data.
0758   ///
0759   /// A number of overloads exist, where you can either supply the
0760   /// @ref HashedString @c key as a template parameter or a runtime argument.  The
0761   /// former has the advantage of being guaranteed to be evaluated at
0762   /// compile-time.
0763   ///
0764   /// @{
0765 
0766   /// Retrieve a mutable reference to a component
0767   /// @tparam T The type of the component to access
0768   /// @tparam key String key for the component to access
0769   /// @return Mutable reference to the component given by @p key
0770   template <typename T, HashedString key, bool RO = ReadOnly,
0771             typename = std::enable_if_t<!RO>>
0772   constexpr T& component() {
0773     return m_container->template component<T, key>(m_index);
0774   }
0775 
0776   /// Retrieve a mutable reference to a component
0777   /// @tparam T The type of the component to access
0778   /// @param key String key for the component to access
0779   /// @return Mutable reference to the component given by @p key
0780   template <typename T, bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0781   constexpr T& component(HashedString key) {
0782     return m_container->template component<T>(key, m_index);
0783   }
0784 
0785   /// Retrieve a mutable reference to a component
0786   /// @tparam T The type of the component to access
0787   /// @param key String key for the component to access
0788   /// @note This might hash the @p key at runtime instead of compile-time
0789   /// @return Mutable reference to the component given by @p key
0790   template <typename T, bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0791   constexpr T& component(std::string_view key) {
0792     return m_container->template component<T>(hashString(key), m_index);
0793   }
0794 
0795   /// Retrieve a const reference to a component
0796   /// @tparam T The type of the component to access
0797   /// @tparam key String key for the component to access
0798   /// @return Const reference to the component given by @p key
0799   template <typename T, HashedString key>
0800   constexpr const T& component() const {
0801     return m_container->template component<T, key>(m_index);
0802   }
0803 
0804   /// Retrieve a const reference to a component
0805   /// @tparam T The type of the component to access
0806   /// @param key String key for the component to access
0807   /// @return Const reference to the component given by @p key
0808   template <typename T>
0809   constexpr const T& component(HashedString key) const {
0810     return m_container->template component<T>(key, m_index);
0811   }
0812 
0813   /// Retrieve a const reference to a component
0814   /// @tparam T The type of the component to access
0815   /// @param key String key for the component to access
0816   /// @note This might hash the @p key at runtime instead of compile-time
0817   /// @return Const reference to the component given by @p key
0818   template <typename T>
0819   constexpr const T& component(std::string_view key) const {
0820     return m_container->template component<T>(hashString(key), m_index);
0821   }
0822 
0823   /// @}
0824 
0825   /// Return the track parameters at the reference surface
0826   /// @note The parameters are created on the fly
0827   /// @return the track parameters
0828   BoundTrackParameters createParametersAtReference() const {
0829     return BoundTrackParameters(referenceSurface().getSharedPtr(), parameters(),
0830                                 covariance(), particleHypothesis());
0831   }
0832 
0833   /// Convert a track state into track parameters
0834   /// @note The parameters are created on the fly
0835   /// @return the track parameters
0836   BoundTrackParameters createParametersFromState(
0837       const ConstTrackStateProxy& trackState) const {
0838     return BoundTrackParameters(trackState.referenceSurface().getSharedPtr(),
0839                                 trackState.parameters(),
0840                                 trackState.covariance(), particleHypothesis());
0841   }
0842 
0843   /// Return a reference to the track container backend, mutable version.
0844   /// @note Only available if the track proxy is not read-only
0845   /// @return reference to the track container backend
0846   template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0847   auto& container() {
0848     return *m_container;
0849   }
0850 
0851   /// Return a reference to the track container backend, const version.
0852   /// @return reference to the track container backend
0853   const auto& container() const {
0854     return *m_container;
0855   }
0856 
0857  private:
0858   TrackProxy(detail_tc::ConstIf<TrackContainer<Container, Trajectory, holder_t>,
0859                                 ReadOnly>& container,
0860              IndexType itrack)
0861       : m_container{&container}, m_index{itrack} {}
0862 
0863   detail_lt::TransitiveConstPointer<detail_tc::ConstIf<
0864       TrackContainer<Container, Trajectory, holder_t>, ReadOnly>>
0865       m_container;
0866   IndexType m_index;
0867 };
0868 }  // namespace Acts