Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-14 08:10:31

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