Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-17 07:46:17

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/Algebra.hpp"
0012 #include "Acts/Definitions/Common.hpp"
0013 #include "Acts/Definitions/TrackParametrization.hpp"
0014 #include "Acts/EventData/TrackParameterHelpers.hpp"
0015 #include "Acts/EventData/TransformationHelpers.hpp"
0016 #include "Acts/EventData/detail/PrintParameters.hpp"
0017 #include "Acts/Utilities/MathHelpers.hpp"
0018 #include "Acts/Utilities/UnitVectors.hpp"
0019 #include "Acts/Utilities/VectorHelpers.hpp"
0020 
0021 #include <cmath>
0022 #include <optional>
0023 
0024 namespace Acts {
0025 
0026 /// Track parameters not bound to a surface for a single track.
0027 ///
0028 /// Parameters and covariance matrix are stored using the free parametrization
0029 /// defined in `enum FreeIndices`.
0030 class FreeTrackParameters {
0031  public:
0032   /// Type alias for bound parameters vector
0033   using ParametersVector = FreeVector;
0034   /// Type alias for covariance matrix
0035   using CovarianceMatrix = FreeMatrix;
0036 
0037   /// Construct from a parameters vector and particle charge.
0038   ///
0039   /// @param params Free parameters vector
0040   /// @param cov Free parameters covariance matrix
0041   /// @param particleHypothesis Particle hypothesis
0042   ///
0043   /// In principle, only the charge magnitude is needed her to allow unambiguous
0044   /// extraction of the absolute momentum. The particle charge is required as
0045   /// an input here to be consistent with the other constructors below that
0046   /// that also take the charge as an input. The charge sign is only used in
0047   /// debug builds to check for consistency with the q/p parameter.
0048   FreeTrackParameters(const FreeVector& params, std::optional<FreeMatrix> cov,
0049                       ParticleHypothesis particleHypothesis)
0050       : m_params(params),
0051         m_cov(std::move(cov)),
0052         m_particleHypothesis(particleHypothesis) {
0053     assert(isFreeVectorValid(m_params) && "Invalid free parameters vector");
0054   }
0055 
0056   /// Construct from four-position, direction, absolute momentum, and charge.
0057   ///
0058   /// @param pos4 Track position/time four-vector
0059   /// @param dir Track direction three-vector; normalization is ignored.
0060   /// @param qOverP Charge over momentum
0061   /// @param cov Free parameters covariance matrix
0062   /// @param particleHypothesis Particle hypothesis
0063   FreeTrackParameters(const Vector4& pos4, const Vector3& dir, double qOverP,
0064                       std::optional<FreeMatrix> cov,
0065                       ParticleHypothesis particleHypothesis)
0066       : m_params(FreeVector::Zero()),
0067         m_cov(std::move(cov)),
0068         m_particleHypothesis(particleHypothesis) {
0069     m_params[eFreePos0] = pos4[ePos0];
0070     m_params[eFreePos1] = pos4[ePos1];
0071     m_params[eFreePos2] = pos4[ePos2];
0072     m_params[eFreeTime] = pos4[eTime];
0073     m_params[eFreeDir0] = dir[eMom0];
0074     m_params[eFreeDir1] = dir[eMom1];
0075     m_params[eFreeDir2] = dir[eMom2];
0076     m_params[eFreeQOverP] = qOverP;
0077 
0078     assert(isFreeVectorValid(m_params) && "Invalid free parameters vector");
0079   }
0080 
0081   /// Construct from four-position, angles, absolute momentum, and charge.
0082   ///
0083   /// @param pos4 Track position/time four-vector
0084   /// @param phi Transverse track direction angle
0085   /// @param theta Longitudinal track direction angle
0086   /// @param qOverP Charge over momentum
0087   /// @param cov Free parameters covariance matrix
0088   /// @param particleHypothesis Particle hypothesis
0089   FreeTrackParameters(const Vector4& pos4, double phi, double theta,
0090                       double qOverP, std::optional<FreeMatrix> cov,
0091                       ParticleHypothesis particleHypothesis)
0092       : m_params(FreeVector::Zero()),
0093         m_cov(std::move(cov)),
0094         m_particleHypothesis(particleHypothesis) {
0095     auto dir = makeDirectionFromPhiTheta(phi, theta);
0096     m_params[eFreePos0] = pos4[ePos0];
0097     m_params[eFreePos1] = pos4[ePos1];
0098     m_params[eFreePos2] = pos4[ePos2];
0099     m_params[eFreeTime] = pos4[eTime];
0100     m_params[eFreeDir0] = dir[eMom0];
0101     m_params[eFreeDir1] = dir[eMom1];
0102     m_params[eFreeDir2] = dir[eMom2];
0103     m_params[eFreeQOverP] = qOverP;
0104 
0105     assert(isFreeVectorValid(m_params) && "Invalid free parameters vector");
0106   }
0107 
0108   /// Parameters vector.
0109   /// @return Const reference to the free parameters vector
0110   const FreeVector& parameters() const { return m_params; }
0111   /// Optional covariance matrix.
0112   /// @return Const reference to the optional covariance matrix
0113   const std::optional<FreeMatrix>& covariance() const { return m_cov; }
0114 
0115   /// Access a single parameter value identified by its index.
0116   ///
0117   /// @tparam kIndex Track parameter index
0118   /// @return The parameter value at the specified index
0119   template <FreeIndices kIndex>
0120   double get() const {
0121     return m_params[kIndex];
0122   }
0123 
0124   /// Space-time position four-vector.
0125   /// @return Four-dimensional position vector (x, y, z, t)
0126   Vector4 fourPosition() const {
0127     Vector4 pos4;
0128     pos4[ePos0] = m_params[eFreePos0];
0129     pos4[ePos1] = m_params[eFreePos1];
0130     pos4[ePos2] = m_params[eFreePos2];
0131     pos4[eTime] = m_params[eFreeTime];
0132     return pos4;
0133   }
0134   /// Spatial position three-vector.
0135   /// @return Three-dimensional position vector (x, y, z)
0136   Vector3 position() const { return m_params.segment<3>(eFreePos0); }
0137   /// Time coordinate.
0138   /// @return The time coordinate value
0139   double time() const { return m_params[eFreeTime]; }
0140 
0141   /// Phi direction.
0142   /// @return The azimuthal angle phi in radians
0143   double phi() const { return VectorHelpers::phi(direction()); }
0144   /// Theta direction.
0145   /// @return The polar angle theta in radians
0146   double theta() const { return VectorHelpers::theta(direction()); }
0147   /// Charge over momentum.
0148   /// @return The charge over momentum ratio
0149   double qOverP() const { return m_params[eFreeQOverP]; }
0150 
0151   /// Unit direction three-vector, i.e. the normalized momentum three-vector.
0152   /// @return Normalized direction vector
0153   Vector3 direction() const {
0154     return m_params.segment<3>(eFreeDir0).normalized();
0155   }
0156   /// Absolute momentum.
0157   /// @return The absolute momentum magnitude
0158   double absoluteMomentum() const {
0159     return m_particleHypothesis.extractMomentum(m_params[eFreeQOverP]);
0160   }
0161   /// Transverse momentum.
0162   /// @return The transverse momentum magnitude
0163   double transverseMomentum() const {
0164     // direction vector w/ arbitrary normalization can be parametrized as
0165     //   [f*sin(theta)*cos(phi), f*sin(theta)*sin(phi), f*cos(theta)]
0166     // w/ f,sin(theta) positive, the transverse magnitude is then
0167     //   sqrt(f^2*sin^2(theta)) = f*sin(theta)
0168     double transverseMagnitude2 =
0169         square(m_params[eFreeDir0]) + square(m_params[eFreeDir1]);
0170     // absolute magnitude is f by construction
0171     double magnitude2 = transverseMagnitude2 + square(m_params[eFreeDir2]);
0172     // such that we can extract sin(theta) = f*sin(theta) / f
0173     return std::sqrt(transverseMagnitude2 / magnitude2) * absoluteMomentum();
0174   }
0175   /// Momentum three-vector.
0176   /// @return Three-dimensional momentum vector
0177   Vector3 momentum() const { return absoluteMomentum() * direction(); }
0178 
0179   /// Particle electric charge.
0180   /// @return The particle electric charge
0181   double charge() const {
0182     return m_particleHypothesis.extractCharge(get<eFreeQOverP>());
0183   }
0184 
0185   /// Particle hypothesis.
0186   /// @return Reference to the particle hypothesis
0187   const ParticleHypothesis& particleHypothesis() const {
0188     return m_particleHypothesis;
0189   }
0190 
0191   /// Reflect the parameters in place.
0192   void reflectInPlace() { m_params = reflectFreeParameters(m_params); }
0193 
0194   /// Reflect the parameters.
0195   /// @return Reflected parameters.
0196   FreeTrackParameters reflect() const {
0197     FreeTrackParameters reflected = *this;
0198     reflected.reflectInPlace();
0199     return reflected;
0200   }
0201 
0202  private:
0203   FreeVector m_params;
0204   std::optional<FreeMatrix> m_cov;
0205   // TODO use [[no_unique_address]] once we switch to C++20
0206   ParticleHypothesis m_particleHypothesis;
0207 
0208   /// Print information to the output stream.
0209   friend std::ostream& operator<<(std::ostream& os,
0210                                   const FreeTrackParameters& tp) {
0211     detail::printFreeParameters(
0212         os, tp.particleHypothesis(), tp.parameters(),
0213         tp.covariance().has_value() ? &tp.covariance().value() : nullptr);
0214     return os;
0215   }
0216 };
0217 
0218 }  // namespace Acts