Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:01:27

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2016-2020 CERN for the benefit of the Acts project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/Definitions/Tolerance.hpp"
0012 #include "Acts/EventData/detail/PrintParameters.hpp"
0013 #include "Acts/EventData/detail/TransformationFreeToBound.hpp"
0014 #include "Acts/Surfaces/Surface.hpp"
0015 #include "Acts/Utilities/UnitVectors.hpp"
0016 #include "Acts/Utilities/detail/periodic.hpp"
0017 
0018 #include <cassert>
0019 #include <cmath>
0020 #include <memory>
0021 #include <type_traits>
0022 
0023 namespace Acts {
0024 
0025 /// Track parameters bound to a reference surface for a single track.
0026 ///
0027 /// @tparam particle_hypothesis_t Helper type to interpret the particle charge/momentum
0028 ///
0029 /// This is intended as a user-facing data class that adds additional accessors
0030 /// and charge/momentum interpretation on top of the pure parameters vector. All
0031 /// parameters and their corresponding covariance matrix are stored in bound
0032 /// parametrization. The specific definition of the local spatial parameters is
0033 /// defined by the associated surface.
0034 ///
0035 /// @note This class holds shared ownership on its reference surface.
0036 template <class particle_hypothesis_t>
0037 class GenericBoundTrackParameters {
0038  public:
0039   using Scalar = ActsScalar;
0040   using ParametersVector = BoundVector;
0041   using CovarianceMatrix = BoundSquareMatrix;
0042   using ParticleHypothesis = particle_hypothesis_t;
0043 
0044   /// Construct from a parameters vector on the surface and particle charge.
0045   ///
0046   /// @param surface Reference surface the parameters are defined on
0047   /// @param params Bound parameters vector
0048   /// @param cov Bound parameters covariance matrix
0049   /// @param particleHypothesis Particle hypothesis
0050   ///
0051   /// In principle, only the charge magnitude is needed her to allow unambiguous
0052   /// extraction of the absolute momentum. The particle charge is required as
0053   /// an input here to be consistent with the other constructors below that
0054   /// that also take the charge as an input. The charge sign is only used in
0055   /// debug builds to check for consistency with the q/p parameter.
0056   GenericBoundTrackParameters(std::shared_ptr<const Surface> surface,
0057                               const ParametersVector& params,
0058                               std::optional<CovarianceMatrix> cov,
0059                               ParticleHypothesis particleHypothesis)
0060       : m_params(params),
0061         m_cov(std::move(cov)),
0062         m_surface(std::move(surface)),
0063         m_particleHypothesis(std::move(particleHypothesis)) {
0064     assert(m_surface);
0065     normalizePhiTheta();
0066   }
0067 
0068   /// Converts a bound track parameter with a different hypothesis.
0069   template <typename other_particle_hypothesis_t>
0070   GenericBoundTrackParameters(
0071       const GenericBoundTrackParameters<other_particle_hypothesis_t>& other)
0072       : GenericBoundTrackParameters(other.referenceSurface().getSharedPtr(),
0073                                     other.parameters(), other.covariance(),
0074                                     other.particleHypothesis()) {}
0075 
0076   /// Factory to construct from four-position, direction, absolute momentum, and
0077   /// charge.
0078   ///
0079   /// @param surface Reference surface the parameters are defined on
0080   /// @param geoCtx Geometry context for the local-to-global transformation
0081   /// @param pos4 Track position/time four-vector
0082   /// @param dir Track direction three-vector; normalization is ignored
0083   /// @param qOverP Charge over momentum
0084   /// @param cov Bound parameters covariance matrix
0085   /// @param particleHypothesis Particle hypothesis
0086   /// @param tolerance Tolerance used for globalToLocal
0087   ///
0088   /// @note The returned result indicates whether the free parameters could
0089   /// successfully be converted to on-surface parameters.
0090   static Result<GenericBoundTrackParameters> create(
0091       std::shared_ptr<const Surface> surface, const GeometryContext& geoCtx,
0092       const Vector4& pos4, const Vector3& dir, Scalar qOverP,
0093       std::optional<CovarianceMatrix> cov,
0094       ParticleHypothesis particleHypothesis,
0095       ActsScalar tolerance = s_onSurfaceTolerance) {
0096     Result<BoundVector> bound = detail::transformFreeToBoundParameters(
0097         pos4.segment<3>(ePos0), pos4[eTime], dir, qOverP, *surface, geoCtx,
0098         tolerance);
0099 
0100     if (!bound.ok()) {
0101       return bound.error();
0102     }
0103 
0104     return GenericBoundTrackParameters{std::move(surface), std::move(*bound),
0105                                        std::move(cov),
0106                                        std::move(particleHypothesis)};
0107   }
0108 
0109   /// Parameters are not default constructible due to the charge type.
0110   GenericBoundTrackParameters() = delete;
0111   GenericBoundTrackParameters(const GenericBoundTrackParameters&) = default;
0112   GenericBoundTrackParameters(GenericBoundTrackParameters&&) = default;
0113   ~GenericBoundTrackParameters() = default;
0114   GenericBoundTrackParameters& operator=(const GenericBoundTrackParameters&) =
0115       default;
0116   GenericBoundTrackParameters& operator=(GenericBoundTrackParameters&&) =
0117       default;
0118 
0119   /// Parameters vector.
0120   ParametersVector& parameters() { return m_params; }
0121   /// Parameters vector.
0122   const ParametersVector& parameters() const { return m_params; }
0123   /// Vector of spatial impact parameters (i.e., d0 and z0)
0124   ActsVector<2> spatialImpactParameters() const { return m_params.head<2>(); }
0125   /// Vector of spatial and temporal impact parameters (i.e., d0, z0, and t)
0126   ActsVector<3> impactParameters() const {
0127     ActsVector<3> ip;
0128     ip.template head<2>() = m_params.template head<2>();
0129     ip(2) = m_params(eBoundTime);
0130     return ip;
0131   }
0132 
0133   /// Optional covariance matrix.
0134   std::optional<CovarianceMatrix>& covariance() { return m_cov; }
0135   /// Optional covariance matrix.
0136   const std::optional<CovarianceMatrix>& covariance() const { return m_cov; }
0137   /// Covariance matrix of the spatial impact parameters (i.e., of d0 and z0)
0138   std::optional<ActsSquareMatrix<2>> spatialImpactParameterCovariance() const {
0139     if (!m_cov.has_value()) {
0140       return std::nullopt;
0141     }
0142 
0143     return m_cov.value().template topLeftCorner<2, 2>();
0144   }
0145 
0146   /// Covariance matrix of the spatial and temporal impact parameters (i.e., of
0147   /// d0, z0, and t)
0148   std::optional<ActsSquareMatrix<3>> impactParameterCovariance() const {
0149     if (!m_cov.has_value()) {
0150       return std::nullopt;
0151     }
0152 
0153     ActsSquareMatrix<3> ipCov;
0154     ipCov.template topLeftCorner<2, 2>() =
0155         m_cov.value().template topLeftCorner<2, 2>();
0156     ipCov.template block<2, 1>(0, 2) =
0157         m_cov.value().template block<2, 1>(0, eBoundTime);
0158     ipCov.template block<1, 2>(2, 0) =
0159         m_cov.value().template block<1, 2>(eBoundTime, 0);
0160     ipCov(2, 2) = m_cov.value()(eBoundTime, eBoundTime);
0161     return ipCov;
0162   }
0163 
0164   /// Access a single parameter value identified by its index.
0165   ///
0166   /// @tparam kIndex Track parameter index
0167   template <BoundIndices kIndex>
0168   Scalar get() const {
0169     return m_params[kIndex];
0170   }
0171 
0172   /// Local spatial position two-vector.
0173   Vector2 localPosition() const { return m_params.segment<2>(eBoundLoc0); }
0174   /// Space-time position four-vector.
0175   ///
0176   /// @param[in] geoCtx Geometry context for the local-to-global
0177   /// transformation
0178   ///
0179   /// This uses the associated surface to transform the local position on
0180   /// the surface to globalcoordinates. This requires a geometry context to
0181   /// select the appropriate transformation and might be a computationally
0182   /// expensive operation.
0183   Vector4 fourPosition(const GeometryContext& geoCtx) const {
0184     Vector4 pos4;
0185     pos4.segment<3>(ePos0) =
0186         m_surface->localToGlobal(geoCtx, localPosition(), direction());
0187     pos4[eTime] = m_params[eBoundTime];
0188     return pos4;
0189   }
0190   /// Spatial position three-vector.
0191   ///
0192   /// @param[in] geoCtx Geometry context for the local-to-global
0193   /// transformation
0194   ///
0195   /// This uses the associated surface to transform the local position on
0196   /// the surface to globalcoordinates. This requires a geometry context to
0197   /// select the appropriate transformation and might be a computationally
0198   /// expensive operation.
0199   Vector3 position(const GeometryContext& geoCtx) const {
0200     return m_surface->localToGlobal(geoCtx, localPosition(), direction());
0201   }
0202   /// Time coordinate.
0203   Scalar time() const { return m_params[eBoundTime]; }
0204 
0205   /// Phi direction.
0206   Scalar phi() const { return m_params[eBoundPhi]; }
0207   /// Theta direction.
0208   Scalar theta() const { return m_params[eBoundTheta]; }
0209   /// Charge over momentum.
0210   Scalar qOverP() const { return m_params[eBoundQOverP]; }
0211 
0212   /// Unit direction three-vector, i.e. the normalized momentum
0213   /// three-vector.
0214   Vector3 direction() const {
0215     return makeDirectionFromPhiTheta(m_params[eBoundPhi],
0216                                      m_params[eBoundTheta]);
0217   }
0218   /// Absolute momentum.
0219   Scalar absoluteMomentum() const {
0220     return m_particleHypothesis.extractMomentum(m_params[eBoundQOverP]);
0221   }
0222   /// Transverse momentum.
0223   Scalar transverseMomentum() const {
0224     return std::sin(m_params[eBoundTheta]) * absoluteMomentum();
0225   }
0226   /// Momentum three-vector.
0227   Vector3 momentum() const { return absoluteMomentum() * direction(); }
0228 
0229   /// Particle electric charge.
0230   Scalar charge() const {
0231     return m_particleHypothesis.extractCharge(get<eBoundQOverP>());
0232   }
0233 
0234   /// Particle hypothesis.
0235   const ParticleHypothesis& particleHypothesis() const {
0236     return m_particleHypothesis;
0237   }
0238 
0239   /// Reference surface onto which the parameters are bound.
0240   const Surface& referenceSurface() const { return *m_surface; }
0241   /// Reference frame in which the local error is defined.
0242   ///
0243   /// @param[in] geoCtx Geometry context for the local-to-global
0244   /// transformation
0245   ///
0246   /// For planar surfaces, this is the transformation local-to-global
0247   /// rotation matrix. For non-planar surfaces, it is the local-to-global
0248   /// rotation matrix of the tangential plane at the track position.
0249   RotationMatrix3 referenceFrame(const GeometryContext& geoCtx) const {
0250     return m_surface->referenceFrame(geoCtx, position(geoCtx), momentum());
0251   }
0252 
0253  private:
0254   BoundVector m_params;
0255   std::optional<BoundSquareMatrix> m_cov;
0256   /// reference surface
0257   std::shared_ptr<const Surface> m_surface;
0258   // TODO use [[no_unique_address]] once we switch to C++20
0259   ParticleHypothesis m_particleHypothesis;
0260 
0261   /// Ensure phi and theta angles are within bounds.
0262   void normalizePhiTheta() {
0263     auto [phi, theta] =
0264         detail::normalizePhiTheta(m_params[eBoundPhi], m_params[eBoundTheta]);
0265     m_params[eBoundPhi] = phi;
0266     m_params[eBoundTheta] = theta;
0267   }
0268 
0269   /// Compare two bound track parameters for bitwise equality.
0270   ///
0271   /// @note Comparing track parameters for bitwise equality is not a good
0272   /// idea.
0273   ///   Depending on the context you might want to compare only the
0274   ///   parameter values, or compare them for compatibility instead of
0275   ///   equality; you might also have different (floating point) thresholds
0276   ///   of equality in different contexts. None of that can be handled by
0277   ///   this operator. Users should think really hard if this is what they
0278   ///   want and we might decided that we will remove this in the future.
0279   friend bool operator==(const GenericBoundTrackParameters& lhs,
0280                          const GenericBoundTrackParameters& rhs) {
0281     return (lhs.m_params == rhs.m_params) && (lhs.m_cov == rhs.m_cov) &&
0282            (lhs.m_surface == rhs.m_surface) &&
0283            (lhs.m_particleHypothesis == rhs.m_particleHypothesis);
0284   }
0285   /// Compare two bound track parameters for bitwise in-equality.
0286   friend bool operator!=(const GenericBoundTrackParameters& lhs,
0287                          const GenericBoundTrackParameters& rhs) {
0288     return !(lhs == rhs);
0289   }
0290   /// Print information to the output stream.
0291   friend std::ostream& operator<<(std::ostream& os,
0292                                   const GenericBoundTrackParameters& tp) {
0293     detail::printBoundParameters(
0294         os, tp.referenceSurface(), tp.parameters(),
0295         tp.covariance().has_value() ? &tp.covariance().value() : nullptr);
0296     return os;
0297   }
0298 };
0299 
0300 }  // namespace Acts