Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-06 07:51:38

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