Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:12:51

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