Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-19 07:57:09

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/SourceLink.hpp"
0013 #include "Acts/EventData/SubspaceHelpers.hpp"
0014 #include "Acts/EventData/TrackStatePropMask.hpp"
0015 #include "Acts/EventData/TrackStateProxyConcept.hpp"
0016 #include "Acts/EventData/TrackStateType.hpp"
0017 #include "Acts/EventData/Types.hpp"
0018 #include "Acts/Surfaces/Surface.hpp"
0019 #include "Acts/Utilities/EigenConcepts.hpp"
0020 #include "Acts/Utilities/HashedString.hpp"
0021 #include "Acts/Utilities/Helpers.hpp"
0022 
0023 #include <cstddef>
0024 #include <ranges>
0025 #include <span>
0026 
0027 #include <Eigen/Core>
0028 
0029 namespace Acts {
0030 
0031 template <typename derived_t>
0032 class MultiTrajectory;
0033 
0034 namespace detail_lt {
0035 
0036 /// Either type T or const T depending on the boolean.
0037 template <typename T, bool select>
0038 using ConstIf = std::conditional_t<select, const T, T>;
0039 
0040 /// Helper type to make a member pointers constness transitive.
0041 template <typename T>
0042 class TransitiveConstPointer {
0043  public:
0044   using element_type = T;
0045   TransitiveConstPointer() = default;
0046   explicit TransitiveConstPointer(T* ptr) : m_ptr{ptr} {}
0047 
0048   template <typename U>
0049   explicit TransitiveConstPointer(const TransitiveConstPointer<U>& other)
0050       : m_ptr{other.ptr()} {}
0051 
0052   template <typename U>
0053   TransitiveConstPointer& operator=(const TransitiveConstPointer<U>& other) {
0054     m_ptr = other.m_ptr;
0055     return *this;
0056   }
0057 
0058   template <typename U>
0059   bool operator==(const TransitiveConstPointer<U>& other) const {
0060     return m_ptr == other.m_ptr;
0061   }
0062 
0063   const T* operator->() const { return m_ptr; }
0064 
0065   T* operator->() { return m_ptr; }
0066 
0067   template <typename U>
0068   friend class TransitiveConstPointer;
0069 
0070   const T& operator*() const { return *m_ptr; }
0071 
0072   T& operator*() { return *m_ptr; }
0073 
0074   explicit operator bool() const { return m_ptr != nullptr; }
0075 
0076  private:
0077   T* ptr() const { return m_ptr; }
0078 
0079   T* m_ptr{nullptr};
0080 };
0081 
0082 /// Type construction helper for fixed size coefficients and associated
0083 /// covariances.
0084 template <std::size_t Size, bool ReadOnlyMaps = true>
0085 struct FixedSizeTypes {
0086   constexpr static auto Flags = Eigen::ColMajor | Eigen::AutoAlign;
0087 
0088   // single items
0089   using Coefficients = Eigen::Matrix<double, Size, 1, Flags>;
0090   using Covariance = Eigen::Matrix<double, Size, Size, Flags>;
0091   using CoefficientsMap = Eigen::Map<ConstIf<Coefficients, ReadOnlyMaps>>;
0092   using CovarianceMap = Eigen::Map<ConstIf<Covariance, ReadOnlyMaps>>;
0093 
0094   using DynamicCoefficients = Eigen::Matrix<double, Eigen::Dynamic, 1, Flags>;
0095   using DynamicCovariance =
0096       Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Flags>;
0097   using DynamicCoefficientsMap =
0098       Eigen::Map<ConstIf<DynamicCoefficients, ReadOnlyMaps>>;
0099   using DynamicCovarianceMap =
0100       Eigen::Map<ConstIf<DynamicCovariance, ReadOnlyMaps>>;
0101 };
0102 
0103 // Type construction helper for dynamic sized coefficients and associated
0104 /// covariances.
0105 template <bool ReadOnlyMaps = true>
0106 struct DynamicSizeTypes {
0107   constexpr static auto Flags = Eigen::ColMajor | Eigen::AutoAlign;
0108 
0109   using Coefficients = Eigen::Matrix<double, Eigen::Dynamic, 1, Flags>;
0110   using Covariance =
0111       Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Flags>;
0112   using CoefficientsMap = Eigen::Map<ConstIf<Coefficients, ReadOnlyMaps>>;
0113   using CovarianceMap = Eigen::Map<ConstIf<Covariance, ReadOnlyMaps>>;
0114 };
0115 
0116 }  // namespace detail_lt
0117 
0118 // This is public
0119 template <std::size_t M, bool ReadOnly = true>
0120 struct TrackStateTraits {
0121   using Parameters =
0122       typename detail_lt::FixedSizeTypes<eBoundSize, ReadOnly>::CoefficientsMap;
0123   using Covariance =
0124       typename detail_lt::FixedSizeTypes<eBoundSize, ReadOnly>::CovarianceMap;
0125   using Calibrated =
0126       typename detail_lt::FixedSizeTypes<M, ReadOnly>::CoefficientsMap;
0127   using CalibratedCovariance =
0128       typename detail_lt::FixedSizeTypes<M, ReadOnly>::CovarianceMap;
0129   using EffectiveCalibrated =
0130       typename detail_lt::DynamicSizeTypes<ReadOnly>::CoefficientsMap;
0131   using EffectiveCalibratedCovariance =
0132       typename detail_lt::DynamicSizeTypes<ReadOnly>::CovarianceMap;
0133 };
0134 
0135 /// Proxy object to access a single point on the trajectory.
0136 ///
0137 /// @tparam SourceLink Type to link back to an original measurement
0138 /// @tparam M          Maximum number of measurement dimensions
0139 /// @tparam read_only  true for read-only access to underlying storage
0140 template <typename trajectory_t, std::size_t M, bool read_only = true>
0141 class TrackStateProxy {
0142  public:
0143   /// Indicates whether this track state proxy is read-only or if it can be
0144   /// modified
0145   static constexpr bool ReadOnly = read_only;
0146 
0147   /// Alias for an associated const track state proxy, with the same backends
0148   using ConstProxyType = TrackStateProxy<trajectory_t, M, true>;
0149 
0150   /// Map-type for a bound parameter vector. This has reference semantics, i.e.
0151   /// points at a matrix by an internal pointer.
0152   using Parameters = typename TrackStateTraits<M, ReadOnly>::Parameters;
0153 
0154   /// Same as @ref Parameters, but with const semantics
0155   using ConstParameters = typename TrackStateTraits<M, true>::Parameters;
0156 
0157   /// Map-type for a bound covariance. This has reference semantics, i.e.
0158   /// points at a matrix by an internal pointer.
0159   using Covariance = typename TrackStateTraits<M, ReadOnly>::Covariance;
0160 
0161   /// Same as @ref Covariance, but with const semantics
0162   using ConstCovariance = typename TrackStateTraits<M, true>::Covariance;
0163 
0164   /// Map-type for a calibrated measurement vector, where the local measurement
0165   /// dimension is variable.
0166   template <std::size_t N>
0167   using Calibrated = typename TrackStateTraits<N, ReadOnly>::Calibrated;
0168 
0169   /// Same as @c Calibrated, but with const semantics
0170   template <std::size_t N>
0171   using ConstCalibrated = typename TrackStateTraits<N, true>::Calibrated;
0172 
0173   /// Map-type for a calibrated measurement covariance matrix, where the local
0174   /// measurement dimension is variable.
0175   template <std::size_t N>
0176   using CalibratedCovariance =
0177       typename TrackStateTraits<N, ReadOnly>::CalibratedCovariance;
0178 
0179   /// Same as @ref CalibratedCovariance, but with const semantics
0180   template <std::size_t N>
0181   using ConstCalibratedCovariance =
0182       typename TrackStateTraits<N, true>::CalibratedCovariance;
0183 
0184   /// Map-type for a measurement vector, where the local measurement dimension
0185   /// is variable.
0186   using EffectiveCalibrated =
0187       typename TrackStateTraits<M, ReadOnly>::EffectiveCalibrated;
0188 
0189   /// Same as @c EffectiveCalibrated, but with const semantics
0190   using ConstEffectiveCalibrated =
0191       typename TrackStateTraits<M, true>::EffectiveCalibrated;
0192 
0193   /// Map-type for a measurement covariance matrix, where the local measurement
0194   /// dimension is variable.
0195   using EffectiveCalibratedCovariance =
0196       typename TrackStateTraits<M, ReadOnly>::EffectiveCalibratedCovariance;
0197 
0198   /// Same as @ref EffectiveCalibratedCovariance, but with const semantics
0199   using ConstEffectiveCalibratedCovariance =
0200       typename TrackStateTraits<M, true>::EffectiveCalibratedCovariance;
0201 
0202   /// The index type of the track state container
0203   using IndexType = TrackIndexType;
0204 
0205   /// Sentinel value that indicates an invalid index
0206   static constexpr IndexType kInvalid = kTrackIndexInvalid;
0207 
0208   /// The track state container backend given as a template parameter
0209   using Trajectory = trajectory_t;
0210 
0211   /// @anchor track_state_proxy_construct
0212   /// @name Constructors and assignment operator
0213   ///
0214   /// Public constructors and assignment operators for @c TrackStateProxy only
0215   /// allow construction from another @c TrackStateProxy. You should generally
0216   /// not have to construct @c TrackStateProxy manually.
0217   ///
0218   /// @{
0219 
0220   /// Copy constructor: const to const or mutable to mutable
0221   /// @param other The other TrackStateProxy to construct from
0222   TrackStateProxy(const TrackStateProxy& other) = default;
0223 
0224   /// Copy assignment operator: const to const or mutable to mutable
0225   /// @param other The other TrackStateProxy to assign from
0226   /// @return Reference to this TrackStateProxy
0227   TrackStateProxy& operator=(const TrackStateProxy& other) = default;
0228 
0229   /// Constructor from mutable TrackStateProxy
0230   /// @note Only available if the track state proxy is read-only
0231   /// @param other The other TrackStateProxy to construct from
0232   explicit TrackStateProxy(const TrackStateProxy<Trajectory, M, false>& other)
0233     requires ReadOnly
0234       : m_traj{other.m_traj}, m_istate{other.m_istate} {}
0235 
0236   /// Assignment operator to from mutable @c TrackStateProxy
0237   /// @param other The other TrackStateProxy to assign from
0238   /// @note Only available if the track state proxy is read-only
0239   /// @return Reference to this TrackStateProxy
0240   TrackStateProxy& operator=(const TrackStateProxy<Trajectory, M, false>& other)
0241     requires ReadOnly
0242   {
0243     m_traj = other.m_traj;
0244     m_istate = other.m_istate;
0245 
0246     return *this;
0247   }
0248 
0249   /// @}
0250 
0251   /// @anchor track_state_proxy_props
0252   /// @name Track state properties
0253   ///
0254   /// Properties of the track state represented by @c TrackStateProxy.
0255   ///
0256   /// Many of these methods come in a @c const and a non-@c const version. The
0257   /// non-@c const version is only available if you have an instance of
0258   /// @c TrackStateProxy that does not have the @c read_only template parameter set to
0259   /// @c true, even if you hold it as an lvalue.
0260   ///
0261   /// The track states each have an index in the track state container. The
0262   /// sequence of track states is implemented as a one or two-way linked list,
0263   /// which uses indices into the same container.
0264   ///
0265   /// Each track state has a @c previous index, which points at the track state
0266   /// immediately preceding. A track state with a @c previous index of @c
0267   /// kInvalid is the first (innermost) track state in a track or track
0268   /// candidate. This is also referred to as a *stem* at the track level.
0269   ///
0270   /// During track finding and fitting, track states are usually appended to the
0271   /// sequence, populating the @c previous index of the new track state. Combinatorial
0272   /// track finding can produce track states which fork in this way, by having
0273   /// more than one track state with the same @c previous index.
0274   ///
0275   /// The track states have static, optional and dynamic properties. Static
0276   /// properties are always present, and can always be retrieved. Optional
0277   /// components use an extra indirection mechanism that coordinates with the
0278   /// backend to allow both not having the component set, or sharing it with
0279   /// other track states. An example is a branching trajectory from track
0280   /// finding which shares the same predicted parameter vector and associated
0281   /// covariance.
0282   ///
0283   /// Optional components are
0284   /// - predicted parameters and covariance
0285   /// - filtered parameters and covariance
0286   /// - smoothed parameters and covariance
0287   /// - jacobian
0288   /// - calibrated measurement info including projector
0289   ///
0290   /// They can be unset via @ref unset, @ref getMask can be used to check which
0291   /// components are present. The first four are shareable between track
0292   /// states via @ref shareFrom.
0293   ///
0294   /// @{
0295 
0296   /// Index within the trajectory.
0297   /// @return the index
0298   IndexType index() const { return m_istate; }
0299 
0300   /// Return the index of the track state `previous` in the track sequence
0301   /// @return The index of the previous track state.
0302   IndexType previous() const {
0303     return component<IndexType, hashString("previous")>();
0304   }
0305 
0306   /// Return a mutable reference to the index of the track state 'previous' in
0307   /// the track sequence
0308   /// @note Only available if the track state proxy is not read-only
0309   /// @return The index of the previous track state.
0310   IndexType& previous()
0311     requires(!ReadOnly)
0312   {
0313     return component<IndexType, hashString("previous")>();
0314   }
0315 
0316   /// Return whether this track state has a previous (parent) track state.
0317   /// @return Boolean indicating whether a previous track state exists
0318   bool hasPrevious() const {
0319     return component<IndexType, hashString("previous")>() != kInvalid;
0320   }
0321 
0322   /// Build a mask that represents all the allocated components of this track
0323   /// state proxy
0324   /// @return The generated mask
0325   TrackStatePropMask getMask() const;
0326 
0327   /// Unset an optional track state component
0328   /// @note Only available if the track state proxy is not read-only
0329   /// @param target The component to unset
0330   void unset(TrackStatePropMask target)
0331     requires(!ReadOnly)
0332   {
0333     m_traj->self().unset(target, m_istate);
0334   }
0335 
0336   /// Add additional components to the track state
0337   /// @note Only available if the track state proxy is not read-only
0338   /// @param mask The bitmask that instructs which components to allocate
0339   void addComponents(TrackStatePropMask mask)
0340     requires(!ReadOnly)
0341   {
0342     m_traj->self().addTrackStateComponents_impl(m_istate, mask);
0343   }
0344 
0345   /// Reference surface.
0346   /// @return the reference surface
0347   const Surface& referenceSurface() const {
0348     assert(hasReferenceSurface() &&
0349            "TrackState does not have reference surface");
0350     return *m_traj->referenceSurface(m_istate);
0351   }
0352 
0353   /// Returns if the track state has a non nullptr surface associated
0354   /// @return whether a surface exists or not
0355   bool hasReferenceSurface() const {
0356     return m_traj->referenceSurface(m_istate) != nullptr;
0357   }
0358 
0359   // NOLINTBEGIN(performance-unnecessary-value-param)
0360   // looks like a false-positive. clang-tidy believes `srf` is not movable.
0361 
0362   /// Set the reference surface to a given value
0363   /// @param srf Shared pointer to the surface to set
0364   /// @note This overload is only present in case @c ReadOnly is false.
0365   void setReferenceSurface(std::shared_ptr<const Surface> srf)
0366     requires(!ReadOnly)
0367   {
0368     m_traj->setReferenceSurface(m_istate, std::move(srf));
0369   }
0370   // NOLINTEND(performance-unnecessary-value-param)
0371 
0372   /// Getter/setter for chi2 value associated with the track state
0373   /// This overload returns a mutable reference, which allows setting a new
0374   /// value directly into the backing store.
0375   /// @note this overload is only enabled in case the proxy is not read-only
0376   /// @return Mutable reference to the chi2 value
0377   float& chi2()
0378     requires(!ReadOnly)
0379   {
0380     return component<float, hashString("chi2")>();
0381   }
0382 
0383   /// Getter for the chi2 value associated with the track state.
0384   /// This overload returns a copy of the chi2 value, and thus does not allow
0385   /// modification of the value in the backing storage.
0386   /// @return the chi2 value of the track state
0387   float chi2() const { return component<float, hashString("chi2")>(); }
0388 
0389   /// Getter for the path length associated with the track state.
0390   /// This overloaded is only enabled if not read-only, and returns a mutable
0391   /// reference.
0392   /// @return Mutable reference to the pathlength.
0393   double& pathLength()
0394     requires(!ReadOnly)
0395   {
0396     return component<double, hashString("pathLength")>();
0397   }
0398 
0399   /// Getter for the path length. Returns a copy of the path length value.
0400   /// @return The path length of this track state
0401   double pathLength() const {
0402     return component<double, hashString("pathLength")>();
0403   }
0404 
0405   /// Getter for the type flags associated with the track state.
0406   /// This overloaded is only enabled if not read-only, and returns a mutable
0407   /// reference.
0408   /// @return reference to the type flags.
0409   TrackStateType typeFlags()
0410     requires(!ReadOnly)
0411   {
0412     return TrackStateType{
0413         component<TrackStateType::raw_type, hashString("typeFlags")>()};
0414   }
0415 
0416   /// Getter for the type flags. Returns a copy of the type flags value.
0417   /// @return The type flags of this track state
0418   ConstTrackStateType typeFlags() const {
0419     return ConstTrackStateType{
0420         component<TrackStateType::raw_type, hashString("typeFlags")>()};
0421   }
0422 
0423   /// @}
0424 
0425   /// @anchor track_state_proxy_params
0426   /// @name Track state parameters
0427   /// @{
0428 
0429   /// Track parameters vector. This tries to be somewhat smart and return the
0430   /// first parameters that are set in this order: predicted -> filtered ->
0431   /// smoothed
0432   /// @return one of predicted, filtered or smoothed parameters
0433   ConstParameters parameters() const;
0434 
0435   /// Track parameters covariance matrix. This tries to be somewhat smart and
0436   /// return the
0437   /// first parameters that are set in this order: predicted -> filtered ->
0438   /// smoothed
0439   /// @return one of predicted, filtered or smoothed covariances
0440   ConstCovariance covariance() const;
0441 
0442   /// Predicted track parameters vector
0443   /// @return The predicted parameters
0444   ConstParameters predicted() const {
0445     assert(has<hashString("predicted")>());
0446     return m_traj->self().parameters(
0447         component<IndexType, hashString("predicted")>());
0448   }
0449 
0450   /// Predicted track parameters vector (non-const version)
0451   /// @return The predicted parameters with mutable access
0452   Parameters predicted()
0453     requires(!ReadOnly)
0454   {
0455     assert(has<hashString("predicted")>());
0456     return m_traj->self().parameters(
0457         component<IndexType, hashString("predicted")>());
0458   }
0459 
0460   /// Predicted track parameters covariance matrix.
0461   /// @return The predicted track parameter covariance
0462   ConstCovariance predictedCovariance() const {
0463     assert(has<hashString("predicted")>());
0464     return m_traj->self().covariance(
0465         component<IndexType, hashString("predicted")>());
0466   }
0467 
0468   /// Predicted track parameters covariance matrix (non-const version)
0469   /// @return The predicted track parameter covariance with mutable access
0470   Covariance predictedCovariance()
0471     requires(!ReadOnly)
0472   {
0473     assert(has<hashString("predicted")>());
0474     return m_traj->self().covariance(
0475         component<IndexType, hashString("predicted")>());
0476   }
0477 
0478   /// Check whether the predicted parameters+covariance is set
0479   /// @return Whether it is set or not
0480   bool hasPredicted() const { return has<hashString("predicted")>(); }
0481 
0482   /// Filtered track parameters vector
0483   /// @return The filtered parameters
0484   /// @note Const version
0485   ConstParameters filtered() const {
0486     assert(has<hashString("filtered")>());
0487     return m_traj->self().parameters(
0488         component<IndexType, hashString("filtered")>());
0489   }
0490 
0491   /// Filtered track parameters vector
0492   /// @return The filtered parameters
0493   /// @note Mutable version
0494   Parameters filtered()
0495     requires(!ReadOnly)
0496   {
0497     assert(has<hashString("filtered")>());
0498     return m_traj->self().parameters(
0499         component<IndexType, hashString("filtered")>());
0500   }
0501 
0502   /// Filtered track parameters covariance matrix
0503   /// @return The filtered parameters covariance
0504   /// @note Const version
0505   ConstCovariance filteredCovariance() const {
0506     assert(has<hashString("filtered")>());
0507     return m_traj->self().covariance(
0508         component<IndexType, hashString("filtered")>());
0509   }
0510 
0511   /// Filtered track parameters covariance matrix
0512   /// @return The filtered parameters covariance
0513   /// @note Mutable version
0514   Covariance filteredCovariance()
0515     requires(!ReadOnly)
0516   {
0517     assert(has<hashString("filtered")>());
0518     return m_traj->self().covariance(
0519         component<IndexType, hashString("filtered")>());
0520   }
0521 
0522   /// Return whether filtered parameters+covariance is set
0523   /// @return Whether it is set
0524   bool hasFiltered() const { return has<hashString("filtered")>(); }
0525 
0526   /// Smoothed track parameters vector
0527   /// @return The smoothed parameters
0528   /// @note Const version
0529   ConstParameters smoothed() const {
0530     assert(has<hashString("smoothed")>());
0531     return m_traj->self().parameters(
0532         component<IndexType, hashString("smoothed")>());
0533   }
0534 
0535   /// Smoothed track parameters vector
0536   /// @return The smoothed parameters
0537   /// @note Mutable version
0538   Parameters smoothed()
0539     requires(!ReadOnly)
0540   {
0541     assert(has<hashString("smoothed")>());
0542     return m_traj->self().parameters(
0543         component<IndexType, hashString("smoothed")>());
0544   }
0545 
0546   /// Smoothed track parameters covariance matrix
0547   /// @return the parameter covariance matrix
0548   /// @note Const version
0549   ConstCovariance smoothedCovariance() const {
0550     assert(has<hashString("smoothed")>());
0551     return m_traj->self().covariance(
0552         component<IndexType, hashString("smoothed")>());
0553   }
0554 
0555   /// Smoothed track parameters covariance matrix
0556   /// @return the parameter covariance matrix
0557   /// @note Mutable version
0558   Covariance smoothedCovariance()
0559     requires(!ReadOnly)
0560   {
0561     assert(has<hashString("smoothed")>());
0562     return m_traj->self().covariance(
0563         component<IndexType, hashString("smoothed")>());
0564   }
0565 
0566   /// Return whether smoothed parameters+covariance is set
0567   /// @return Whether it is set
0568   bool hasSmoothed() const { return has<hashString("smoothed")>(); }
0569 
0570   /// Returns the jacobian from the previous trackstate to this one
0571   /// @return The jacobian matrix
0572   /// @note Const version
0573   ConstCovariance jacobian() const {
0574     assert(has<hashString("jacobian")>());
0575     return m_traj->self().jacobian(m_istate);
0576   }
0577 
0578   /// Returns the jacobian from the previous trackstate to this one
0579   /// @return The jacobian matrix
0580   /// @note Mutable version
0581   Covariance jacobian()
0582     requires(!ReadOnly)
0583   {
0584     assert(has<hashString("jacobian")>());
0585     return m_traj->self().jacobian(m_istate);
0586   }
0587 
0588   /// Returns whether a jacobian is set for this trackstate
0589   /// @return Whether it is set
0590   bool hasJacobian() const { return has<hashString("jacobian")>(); }
0591 
0592   /// @}
0593 
0594   /// @anchor track_state_proxy_meas
0595   /// @name Track state measurement properties
0596   ///
0597   /// Properties of the measurement associated with the track state represented.
0598   /// This consists of a vector and an associated square matrix of a measurement
0599   /// dimension which is between one and the size of the track parametrization.
0600   /// The measurement coordinate frame is required to be a strict subset of the
0601   /// bound track parametrization on the local geometry coordinate frame, i.e.
0602   /// using a pure projector matrix to convert from the bound parametrization to
0603   /// the measurement frame is possible.
0604   ///
0605   /// The track state stores the parameter vector and covariance, and the
0606   /// backend is given the possibility to do so in a jagged way, i.e. only
0607   /// storing the number of values needed. This requires calling
0608   /// @ref allocateCalibrated before storing the measurements
0609   /// (even if it might be a no-op).
0610   ///
0611   /// The projector matrix is packed as a bitset, which is converted to a matrix
0612   /// on-demand (and therefore returned by value).
0613   ///
0614   /// The track state also includes a @ref SourceLink which acts as a proxy
0615   /// to the original uncalibrated measurement that the calibrated measurement
0616   /// was derived from. It is set and returned by value, to allow unpacking /
0617   /// repacking by the backend, if needed.
0618   ///
0619   /// @{
0620 
0621   /// Set the projector subspace indices
0622   /// @param subspaceIndices The projector subspace indices to set
0623   template <std::ranges::sized_range index_range_t>
0624   void setProjectorSubspaceIndices(const index_range_t& subspaceIndices)
0625     requires(!ReadOnly &&
0626              std::convertible_to<std::ranges::range_value_t<index_range_t>,
0627                                  std::uint8_t>)
0628   {
0629     assert(has<hashString("projector")>());
0630     assert(subspaceIndices.size() <= eBoundSize);
0631     BoundSubspaceIndices boundSubspace{};
0632     std::transform(subspaceIndices.begin(), subspaceIndices.end(),
0633                    boundSubspace.begin(),
0634                    [](auto i) { return static_cast<std::uint8_t>(i); });
0635     component<SerializedSubspaceIndices, hashString("projector")>() =
0636         serializeSubspaceIndices(boundSubspace);
0637   }
0638 
0639   /// Returns whether a projector is set
0640   /// @return Whether it is set
0641   bool hasProjector() const { return has<hashString("projector")>(); }
0642 
0643   /// Returns the projector subspace indices
0644   /// @return The projector subspace indices
0645   BoundSubspaceIndices projectorSubspaceIndices() const {
0646     assert(has<hashString("projector")>());
0647     return deserializeSubspaceIndices<eBoundSize>(
0648         component<SerializedSubspaceIndices, hashString("projector")>());
0649   }
0650 
0651   /// Returns the projector subspace indices
0652   /// @return The projector subspace indices
0653   template <std::size_t measdim>
0654   SubspaceIndices<measdim> projectorSubspaceIndices() const {
0655     BoundSubspaceIndices boundSubspace = projectorSubspaceIndices();
0656     SubspaceIndices<measdim> subspace;
0657     std::copy(boundSubspace.begin(), boundSubspace.begin() + measdim,
0658               subspace.begin());
0659     return subspace;
0660   }
0661 
0662   /// Creates a variable size subspace helper
0663   /// @return The subspace helper
0664   VariableBoundSubspaceHelper projectorSubspaceHelper() const {
0665     BoundSubspaceIndices boundSubspace = projectorSubspaceIndices();
0666     std::span<std::uint8_t> validSubspaceIndices(
0667         boundSubspace.begin(), boundSubspace.begin() + calibratedSize());
0668     return VariableBoundSubspaceHelper(validSubspaceIndices);
0669   }
0670 
0671   /// Creates a fixed size subspace helper
0672   /// @return The subspace helper
0673   template <std::size_t measdim>
0674   FixedBoundSubspaceHelper<measdim> projectorSubspaceHelper() const {
0675     SubspaceIndices<measdim> subspace = projectorSubspaceIndices<measdim>();
0676     return FixedBoundSubspaceHelper<measdim>(subspace);
0677   }
0678 
0679   /// Uncalibrated measurement in the form of a source link. Const version
0680   /// @return The uncalibrated measurement source link
0681   SourceLink getUncalibratedSourceLink() const;
0682 
0683   /// Set an uncalibrated source link
0684   /// @param sourceLink The uncalibrated source link to set
0685   void setUncalibratedSourceLink(SourceLink&& sourceLink)
0686     requires(!ReadOnly)
0687   {
0688     m_traj->setUncalibratedSourceLink(m_istate, std::move(sourceLink));
0689   }
0690 
0691   /// Check if the point has an associated uncalibrated measurement.
0692   /// @return Whether it is set
0693   bool hasUncalibratedSourceLink() const {
0694     return has<hashString("uncalibratedSourceLink")>();
0695   }
0696 
0697   /// Check if the point has an associated calibrated measurement.
0698   /// @return Whether it is set
0699   bool hasCalibrated() const { return has<hashString("calibrated")>(); }
0700 
0701   /// Full calibrated measurement vector. Might contain additional zeroed
0702   /// dimensions.
0703   /// @return The measurement vector
0704   /// @note Const version
0705   template <std::size_t measdim>
0706   ConstCalibrated<measdim> calibrated() const {
0707     assert(has<hashString("calibrated")>());
0708     return m_traj->self().template calibrated<measdim>(m_istate);
0709   }
0710 
0711   /// Full calibrated measurement vector. Might contain additional zeroed
0712   /// dimensions.
0713   /// @return The measurement vector
0714   /// @note Mutable version
0715   template <std::size_t measdim>
0716   Calibrated<measdim> calibrated()
0717     requires(!ReadOnly)
0718   {
0719     assert(has<hashString("calibrated")>());
0720     return m_traj->self().template calibrated<measdim>(m_istate);
0721   }
0722 
0723   /// Const full calibrated measurement covariance matrix. The effective
0724   /// covariance is located in the top left corner, everything else is zeroed.
0725   /// @return The measurement covariance matrix
0726   template <std::size_t measdim>
0727   ConstCalibratedCovariance<measdim> calibratedCovariance() const {
0728     assert(has<hashString("calibratedCov")>());
0729     return m_traj->self().template calibratedCovariance<measdim>(m_istate);
0730   }
0731 
0732   /// Mutable full calibrated measurement covariance matrix. The effective
0733   /// covariance is located in the top left corner, everything else is zeroed.
0734   /// @return The measurement covariance matrix
0735   template <std::size_t measdim>
0736   CalibratedCovariance<measdim> calibratedCovariance()
0737     requires(!ReadOnly)
0738   {
0739     assert(has<hashString("calibratedCov")>());
0740     return m_traj->self().template calibratedCovariance<measdim>(m_istate);
0741   }
0742 
0743   /// Mutable dynamic measurement vector with only the valid dimensions.
0744   /// @warning The dynamic vector has a runtime overhead!
0745   /// @return The effective calibrated measurement vector
0746   EffectiveCalibrated effectiveCalibrated()
0747     requires(!ReadOnly)
0748   {
0749     assert(has<hashString("calibrated")>());
0750     return m_traj->self().effectiveCalibrated(m_istate);
0751   }
0752 
0753   /// Const dynamic measurement vector with only the valid dimensions.
0754   /// @warning The dynamic matrix has a runtime overhead!
0755   /// @return The effective calibrated measurement vector
0756   ConstEffectiveCalibrated effectiveCalibrated() const {
0757     assert(has<hashString("calibrated")>());
0758     return m_traj->self().effectiveCalibrated(m_istate);
0759   }
0760 
0761   /// Mutable dynamic measurement covariance matrix with only the valid
0762   /// dimensions.
0763   /// @warning The dynamic matrix has a runtime overhead!
0764   /// @return The effective calibrated covariance matrix
0765   EffectiveCalibratedCovariance effectiveCalibratedCovariance() {
0766     assert(has<hashString("calibratedCov")>());
0767     return m_traj->self().effectiveCalibratedCovariance(m_istate);
0768   }
0769 
0770   /// Const dynamic measurement covariance matrix with only the valid
0771   /// dimensions.
0772   /// @warning The dynamic matrix has a runtime overhead!
0773   /// @return The effective calibrated covariance matrix
0774   ConstEffectiveCalibratedCovariance effectiveCalibratedCovariance() const {
0775     assert(has<hashString("calibratedCov")>());
0776     return m_traj->self().effectiveCalibratedCovariance(m_istate);
0777   }
0778 
0779   /// Return the (dynamic) number of dimensions stored for this measurement.
0780   /// @note Depending on the backend, this size is used to determine the
0781   ///       memory range of the measurement vector and covariance.
0782   /// @return The number of dimensions
0783   IndexType calibratedSize() const { return m_traj->calibratedSize(m_istate); }
0784 
0785   /// Allocate storage to be able to store a measurement of size @p measdim.
0786   /// This must be called **before** setting the measurement content.
0787   /// @param measdim Number of measurement dimensions to allocate
0788   /// @note This does not allocate if an allocation of the same size already exists
0789   /// @note This will zero-initialize the allocated storage
0790   /// @note This is an error if an existing allocation has different size
0791   void allocateCalibrated(std::size_t measdim) {
0792     m_traj->allocateCalibrated(m_istate, measdim);
0793   }
0794 
0795   /// Allocate storage and assign the given vector and covariance to it.
0796   /// The dimension is inferred from the given vector and matrix.
0797   /// @tparam val_t Type of the vector
0798   /// @tparam cov_t Type of the covariance matrix
0799   /// @param val The measurement vector
0800   /// @param cov The covariance matrix
0801   /// @note This does not allocate if an allocation of the same size already exists
0802   /// @note This throws an exception if an existing allocation has different size
0803   template <typename val_t, typename cov_t>
0804   void allocateCalibrated(const Eigen::DenseBase<val_t>& val,
0805                           const Eigen::DenseBase<cov_t>& cov)
0806     requires(Concepts::eigen_base_is_fixed_size<val_t> &&
0807              Concepts::eigen_bases_have_same_num_rows<val_t, cov_t> &&
0808              Concepts::eigen_base_is_square<cov_t> &&
0809              Eigen::PlainObjectBase<val_t>::RowsAtCompileTime <=
0810                  static_cast<std::underlying_type_t<BoundIndices>>(eBoundSize))
0811   {
0812     m_traj->template allocateCalibrated<
0813         Eigen::PlainObjectBase<val_t>::RowsAtCompileTime>(m_istate, val, cov);
0814   }
0815 
0816   /// @}
0817 
0818   /// @anchor track_state_share_copy
0819   /// @name Sharing and copying
0820   ///
0821   /// Methods to share and copy track state components. Sharing means setting up
0822   /// more than one track state to point to the same component.
0823   ///
0824   /// Shareable components are
0825   /// - predicted parameters and covariance
0826   /// - filtered parameters and covariance
0827   /// - smoothed parameters and covariance
0828   /// - jacobian
0829   ///
0830   /// See @ref TrackStatePropMask.
0831   ///
0832   /// @{
0833 
0834   /// Share a shareable component **within** this track state
0835   /// @param shareSource Which component to share from
0836   /// @param shareTarget Which component to share as. This should be different from
0837   ///                    as @p shareSource, e.g. predicted can be shared as filtered.
0838   void shareFrom(TrackStatePropMask shareSource, TrackStatePropMask shareTarget)
0839     requires(!ReadOnly)
0840   {
0841     shareFrom(*this, shareSource, shareTarget);
0842   }
0843 
0844   /// Share a shareable component from another track state.
0845   /// @param other Track state proxy to share component from
0846   /// @param component Which component to share.
0847   /// @note The track states both need to be stored in the
0848   ///       same @c MultiTrajectory instance
0849   template <bool ReadOnlyOther>
0850   void shareFrom(const TrackStateProxy<Trajectory, M, ReadOnlyOther>& other,
0851                  TrackStatePropMask component)
0852     requires(!ReadOnly)
0853   {
0854     shareFrom(other, component, component);
0855   }
0856 
0857   /// Share a shareable component from another track state
0858   /// @param other Track state proxy to share component(s) from
0859   /// @param shareSource Which component to share from
0860   /// @param shareTarget Which component to share as. This can be be different from
0861   ///                    as @p shareSource, e.g. predicted can be shared as filtered.
0862   /// @note Shareable components are predicted, filtered, smoothed, calibrated, jacobian,
0863   ///       or projector. See @c TrackStatePropMask.
0864   template <bool ReadOnlyOther>
0865   void shareFrom(const TrackStateProxy<Trajectory, M, ReadOnlyOther>& other,
0866                  TrackStatePropMask shareSource, TrackStatePropMask shareTarget)
0867     requires(!ReadOnly)
0868   {
0869     assert(m_traj == other.m_traj &&
0870            "Cannot share components across MultiTrajectories");
0871 
0872     assert(ACTS_CHECK_BIT(other.getMask(), shareSource) &&
0873            "Source has incompatible allocation");
0874 
0875     m_traj->self().shareFrom(m_istate, other.m_istate, shareSource,
0876                              shareTarget);
0877   }
0878 
0879   /// Copy the contents of another track state proxy into this one
0880   /// @param other The other track state to copy from
0881   /// @param mask An optional mask to determine what to copy from
0882   /// @param onlyAllocated Whether to only copy allocated components
0883   /// @note If the this track state proxy does not have compatible allocations
0884   ///       with the source track state proxy, and @p onlyAllocated is false,
0885   ///       an exception is thrown.
0886   /// @note The mask parameter will not cause a copy of components that are
0887   ///       not allocated in the source track state proxy.
0888   template <TrackStateProxyConcept track_state_proxy_t>
0889   void copyFrom(const track_state_proxy_t& other,
0890                 TrackStatePropMask mask = TrackStatePropMask::All,
0891                 bool onlyAllocated = true)
0892     requires(!ReadOnly)
0893   {
0894     using PM = TrackStatePropMask;
0895 
0896     if (onlyAllocated) {
0897       auto dest = getMask();
0898       auto src = other.getMask() &
0899                  mask;  // combine what we have with what we want to copy
0900 
0901       if (ACTS_CHECK_BIT(src, PM::Calibrated)) {
0902         // on-demand allocate calibrated
0903         dest |= PM::Calibrated;
0904       }
0905 
0906       if ((static_cast<std::underlying_type_t<TrackStatePropMask>>(
0907                (src ^ dest) & src) != 0 ||
0908            dest == TrackStatePropMask::None ||
0909            src == TrackStatePropMask::None) &&
0910           mask != TrackStatePropMask::None) {
0911         throw std::runtime_error(
0912             "Attempt track state copy with incompatible allocations");
0913       }
0914 
0915       // we're sure now this has correct allocations, so just copy
0916       if (ACTS_CHECK_BIT(src, PM::Predicted)) {
0917         predicted() = other.predicted();
0918         predictedCovariance() = other.predictedCovariance();
0919       }
0920 
0921       if (ACTS_CHECK_BIT(src, PM::Filtered)) {
0922         filtered() = other.filtered();
0923         filteredCovariance() = other.filteredCovariance();
0924       }
0925 
0926       if (ACTS_CHECK_BIT(src, PM::Smoothed)) {
0927         smoothed() = other.smoothed();
0928         smoothedCovariance() = other.smoothedCovariance();
0929       }
0930 
0931       if (other.hasUncalibratedSourceLink()) {
0932         setUncalibratedSourceLink(other.getUncalibratedSourceLink());
0933       }
0934 
0935       if (ACTS_CHECK_BIT(src, PM::Jacobian)) {
0936         jacobian() = other.jacobian();
0937       }
0938 
0939       if (ACTS_CHECK_BIT(src, PM::Calibrated)) {
0940         // workaround for gcc8 bug:
0941         // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86594
0942         auto* self = this;
0943         visit_measurement(other.calibratedSize(), [&](auto N) {
0944           constexpr int measdim = decltype(N)::value;
0945           self->allocateCalibrated(
0946               other.template calibrated<measdim>().eval(),
0947               other.template calibratedCovariance<measdim>().eval());
0948         });
0949 
0950         setProjectorSubspaceIndices(other.projectorSubspaceIndices());
0951       }
0952     } else {
0953       if (ACTS_CHECK_BIT(mask, PM::Predicted) &&
0954           has<hashString("predicted")>() &&
0955           other.template has<hashString("predicted")>()) {
0956         predicted() = other.predicted();
0957         predictedCovariance() = other.predictedCovariance();
0958       }
0959 
0960       if (ACTS_CHECK_BIT(mask, PM::Filtered) && has<hashString("filtered")>() &&
0961           other.template has<hashString("filtered")>()) {
0962         filtered() = other.filtered();
0963         filteredCovariance() = other.filteredCovariance();
0964       }
0965 
0966       if (ACTS_CHECK_BIT(mask, PM::Smoothed) && has<hashString("smoothed")>() &&
0967           other.template has<hashString("smoothed")>()) {
0968         smoothed() = other.smoothed();
0969         smoothedCovariance() = other.smoothedCovariance();
0970       }
0971 
0972       if (other.hasUncalibratedSourceLink()) {
0973         setUncalibratedSourceLink(other.getUncalibratedSourceLink());
0974       }
0975 
0976       if (ACTS_CHECK_BIT(mask, PM::Jacobian) && has<hashString("jacobian")>() &&
0977           other.template has<hashString("jacobian")>()) {
0978         jacobian() = other.jacobian();
0979       }
0980 
0981       // NOTE: we should not check hasCalibrated on this, since it
0982       // may be not yet allocated
0983       if (ACTS_CHECK_BIT(mask, PM::Calibrated) &&
0984           other.template has<hashString("calibrated")>()) {
0985         // workaround for gcc8 bug:
0986         // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86594
0987         auto* self = this;
0988         visit_measurement(other.calibratedSize(), [&](auto N) {
0989           constexpr int measdim = decltype(N)::value;
0990           self->allocateCalibrated(
0991               other.template calibrated<measdim>().eval(),
0992               other.template calibratedCovariance<measdim>().eval());
0993         });
0994 
0995         setProjectorSubspaceIndices(other.projectorSubspaceIndices());
0996       }
0997     }
0998 
0999     chi2() = other.chi2();
1000     pathLength() = other.pathLength();
1001     typeFlags() = other.typeFlags();
1002 
1003     if (other.hasReferenceSurface()) {
1004       setReferenceSurface(other.referenceSurface().getSharedPtr());
1005     }
1006 
1007     m_traj->copyDynamicFrom(m_istate, other.container(), other.index());
1008   }
1009 
1010   /// @}
1011 
1012   /// @anchor track_state_proxy_generic_component
1013   /// @name Track state proxy Generic component access
1014   /// @{
1015 
1016   /// Check if a component is set
1017   /// @tparam key Hashed string key to check for
1018   /// @return true if the component exists, false if not
1019   template <HashedString key>
1020   constexpr bool has() const {
1021     return m_traj->template has<key>(m_istate);
1022   }
1023 
1024   /// Check if a component is set
1025   /// @param key Hashed string key to check for
1026   /// @return true if the component exists, false if not
1027   constexpr bool has(HashedString key) const {
1028     return m_traj->has(key, m_istate);
1029   }
1030 
1031   /// Check if a component is set
1032   /// @param key String key to check for
1033   /// @note This might hash the @p key at runtime instead of compile-time
1034   /// @return true if the component exists, false if not
1035   constexpr bool has(std::string_view key) const {
1036     return has(hashStringDynamic(key));
1037   }
1038 
1039   /// Retrieve a mutable reference to a component
1040   /// @tparam T The type of the component to access
1041   /// @tparam key String key for the component to access
1042   /// @return Mutable reference to the component given by @p key
1043   template <typename T, HashedString key>
1044   constexpr T& component()
1045     requires(!ReadOnly)
1046   {
1047     return m_traj->template component<T, key>(m_istate);
1048   }
1049 
1050   /// Retrieve a mutable reference to a component
1051   /// @tparam T The type of the component to access
1052   /// @param key String key for the component to access
1053   /// @return Mutable reference to the component given by @p key
1054   template <typename T>
1055   constexpr T& component(HashedString key)
1056     requires(!ReadOnly)
1057   {
1058     return m_traj->template component<T>(key, m_istate);
1059   }
1060 
1061   /// Retrieve a mutable reference to a component
1062   /// @tparam T The type of the component to access
1063   /// @param key String key for the component to access
1064   /// @note This might hash the @p key at runtime instead of compile-time
1065   /// @return Mutable reference to the component given by @p key
1066   template <typename T>
1067   constexpr T& component(std::string_view key)
1068     requires(!ReadOnly)
1069   {
1070     return m_traj->template component<T>(hashStringDynamic(key), m_istate);
1071   }
1072 
1073   /// Retrieve a const reference to a component
1074   /// @tparam T The type of the component to access
1075   /// @tparam key String key for the component to access
1076   /// @return Const reference to the component given by @p key
1077   template <typename T, HashedString key>
1078   constexpr const T& component() const {
1079     return m_traj->template component<T, key>(m_istate);
1080   }
1081 
1082   /// Retrieve a const reference to a component
1083   /// @tparam T The type of the component to access
1084   /// @param key String key for the component to access
1085   /// @return Const reference to the component given by @p key
1086   template <typename T>
1087   constexpr const T& component(HashedString key) const {
1088     return m_traj->template component<T>(key, m_istate);
1089   }
1090 
1091   /// Retrieve a const reference to a component
1092   /// @tparam T The type of the component to access
1093   /// @param key String key for the component to access
1094   /// @note This might hash the @p key at runtime instead of compile-time
1095   /// @return Const reference to the component given by @p key
1096   template <typename T>
1097   constexpr const T& component(std::string_view key) const {
1098     return m_traj->template component<T>(hashStringDynamic(key), m_istate);
1099   }
1100 
1101   /// @}
1102 
1103   /// Return a mutable reference to the underlying backend container
1104   /// @return A reference to the backend container
1105   MultiTrajectory<Trajectory>& trajectory()
1106     requires(!ReadOnly)
1107   {
1108     return *m_traj;
1109   }
1110 
1111   /// Return a const reference to the underlying backend container
1112   /// @return A const reference to the backend container
1113   const MultiTrajectory<Trajectory>& trajectory() const { return *m_traj; }
1114 
1115   /// Get a mutable reference to the track state container backend
1116   /// @return a mutable reference to the backend
1117   auto& container()
1118     requires(!ReadOnly)
1119   {
1120     return *m_traj;
1121   }
1122 
1123   /// Get a const reference to the track state container backend
1124   /// @return a const reference to the backend
1125   const auto& container() const { return *m_traj; }
1126 
1127  private:
1128   // Private since it can only be created by the trajectory.
1129   TrackStateProxy(
1130       detail_lt::ConstIf<MultiTrajectory<Trajectory>, ReadOnly>& trajectory,
1131       IndexType istate);
1132 
1133   detail_lt::TransitiveConstPointer<
1134       detail_lt::ConstIf<MultiTrajectory<Trajectory>, ReadOnly>>
1135       m_traj;
1136   IndexType m_istate;
1137 
1138   friend class Acts::MultiTrajectory<Trajectory>;
1139   friend class TrackStateProxy<Trajectory, M, true>;
1140   friend class TrackStateProxy<Trajectory, M, false>;
1141 };
1142 }  // namespace Acts
1143 
1144 #include "Acts/EventData/TrackStateProxy.ipp"