Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:10:50

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