Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-14 08:10:52

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/EventData/TrackParameters.hpp"
0013 #include "Acts/Geometry/GeometryContext.hpp"
0014 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0015 #include "Acts/MagneticField/MagneticFieldProvider.hpp"
0016 #include "Acts/MagneticField/NullBField.hpp"
0017 #include "Acts/Propagator/Propagator.hpp"
0018 #include "Acts/Utilities/Logger.hpp"
0019 #include "Acts/Utilities/Result.hpp"
0020 #include "Acts/Vertexing/TrackAtVertex.hpp"
0021 #include "Acts/Vertexing/Vertex.hpp"
0022 
0023 namespace Acts {
0024 
0025 struct ImpactParametersAndSigma {
0026   // Impact parameters ...
0027   double d0 = 0.;
0028   double z0 = 0.;
0029   // ... and their standard deviations wrt a vertex, e.g.:
0030   // sigmaD0 = sqrt(Var(X) + Var(Y) + Var(d0)),
0031   // where X and Y are the x- and y-coordinate of the vertex
0032   double sigmaD0 = 0.;
0033   double sigmaZ0 = 0.;
0034   // Absolute difference in time between the vertex and the track at the 2D PCA
0035   // ...
0036   std::optional<double> deltaT = std::nullopt;
0037   // ... and standard deviation wrt a vertex
0038   std::optional<double> sigmaDeltaT = std::nullopt;
0039 };
0040 
0041 /// @class ImpactPointEstimator
0042 ///
0043 /// @brief Estimator for impact point calculations
0044 /// A description of the underlying mathematics can be found here:
0045 /// https://github.com/acts-project/acts/pull/2506
0046 /// TODO: Upload reference at a better place
0047 class ImpactPointEstimator {
0048  public:
0049   /// State struct
0050   struct State {
0051     /// Magnetic field cache
0052     MagneticFieldProvider::Cache fieldCache;
0053   };
0054 
0055   struct Config {
0056     /// @brief Config constructor if magnetic field is present
0057     ///
0058     /// @param bIn The magnetic field
0059     /// @param prop The propagator
0060     explicit Config(std::shared_ptr<const MagneticFieldProvider> bIn,
0061                     std::shared_ptr<const BasePropagator> prop)
0062         : bField(std::move(bIn)), propagator(std::move(prop)) {}
0063 
0064     /// @brief Config constructor without B field -> uses NullBField
0065     /// provided)
0066     ///
0067     /// @param prop The propagator
0068     explicit Config(std::shared_ptr<const BasePropagator> prop)
0069         : bField{std::make_shared<NullBField>()}, propagator(std::move(prop)) {}
0070 
0071     /// Magnetic field
0072     std::shared_ptr<const MagneticFieldProvider> bField;
0073     /// Propagator
0074     std::shared_ptr<const BasePropagator> propagator;
0075     /// Max. number of iterations in Newton method
0076     int maxIterations = 20;
0077     /// Desired precision of deltaPhi in Newton method
0078     double precision = 1.e-10;
0079   };
0080 
0081   /// @brief Constructor
0082   ///
0083   /// @param cfg Configuration object
0084   /// @param logger Logging instance
0085   explicit ImpactPointEstimator(const Config& cfg,
0086                                 std::unique_ptr<const Logger> logger =
0087                                     getDefaultLogger("ImpactPointEstimator",
0088                                                      Logging::INFO))
0089       : m_cfg(cfg), m_logger(std::move(logger)) {}
0090 
0091   /// @brief Copy constructor to clone logger (class owns a unique pointer to it,
0092   /// which can't be copied)
0093   ///
0094   /// @param other Impact point estimator to be cloned
0095   ImpactPointEstimator(const ImpactPointEstimator& other)
0096       : m_cfg(other.m_cfg), m_logger(other.logger().clone()) {}
0097 
0098   /// Move constructor for impact point estimator
0099   ImpactPointEstimator(ImpactPointEstimator&&) = default;
0100 
0101   /// @brief Calculates 3D distance between a track and a vertex
0102   ///
0103   /// @param gctx The geometry context
0104   /// @param trkParams Track parameters
0105   /// @param vtxPos 3D position to calculate the distance to
0106   /// @param state The state object
0107   ///
0108   /// @return Distance
0109   Result<double> calculateDistance(const GeometryContext& gctx,
0110                                    const BoundTrackParameters& trkParams,
0111                                    const Vector3& vtxPos, State& state) const;
0112 
0113   /// @brief Estimates the track parameters at the 3D PCA (i.e., a point of
0114   /// minimal 3D distance) to a vertex. The track parameters are defined wrt a
0115   /// reference plane that has its origin at the vertex position and whose
0116   /// z-axis points in the direction of the track momentum. The plane's x-axis
0117   /// points approximately from the vertex to the 3D PCA (it is only approximate
0118   /// because we force it to be orthogonal to the z-axis). The y-axis is
0119   /// calculated as a cross product between x- and z-axis.
0120   ///
0121   /// @param gctx The geometry context
0122   /// @param mctx The magnetic field context
0123   /// @param trkParams Track parameters
0124   /// @param vtxPos Reference position (vertex)
0125   /// @param state The state object
0126   ///
0127   /// @return Track parameters at the 3D PCA
0128   Result<BoundTrackParameters> estimate3DImpactParameters(
0129       const GeometryContext& gctx, const Acts::MagneticFieldContext& mctx,
0130       const BoundTrackParameters& trkParams, const Vector3& vtxPos,
0131       State& state) const;
0132 
0133   /// @brief Estimates the compatibility of a track to a vertex based on their
0134   /// 3D (if nDim = 3) or 4D (if nDim = 4) distance and the track covariance.
0135   /// @note Confusingly, a *smaller* compatibility means that a track is *more*
0136   /// compatible.
0137   ///
0138   /// @tparam nDim Number of dimensions used to compute compatibility
0139   /// @note If @p nDim = 3 we only consider spatial dimensions; if nDim = 4, we
0140   ///       also consider time. Other values are not allowed.
0141   /// @param gctx The Geometry context
0142   /// @param trkParams Track parameters at point of closest
0143   /// approach in 3D as retrieved by estimate3DImpactParameters
0144   /// @param vertexPos The vertex position
0145   ///
0146   /// @return The compatibility value
0147   template <int nDim>
0148   Result<double> getVertexCompatibility(
0149       const GeometryContext& gctx, const BoundTrackParameters* trkParams,
0150       const ActsVector<nDim>& vertexPos) const {
0151     static_assert(nDim == 3 || nDim == 4,
0152                   "Only 3D and 4D vertex positions allowed");
0153     return getVertexCompatibility(gctx, trkParams, {vertexPos.data(), nDim});
0154   }
0155 
0156   /// @brief Calculate the distance between a track and a vertex by finding the
0157   /// corresponding 3D PCA. Returns also the momentum direction at the 3D PCA.
0158   /// The template parameter nDim determines whether we calculate the 3D
0159   /// distance (nDim = 3) or the 4D distance (nDim = 4) to the 3D PCA.
0160   /// @note For straight tracks we use an analytical solution; for helical
0161   /// tracks we use the Newton method.
0162   ///
0163   /// @tparam nDim Number of dimensions used to compute compatibility
0164   /// @note If @p nDim = 3 we only consider spatial dimensions; if nDim = 4, we
0165   ///       also consider time. Other values are not allowed.
0166   /// @param gctx Geometry context
0167   /// @param trkParams Track parameters
0168   /// @param vtxPos Vertex position
0169   /// @param state The state object
0170   template <int nDim>
0171   Result<std::pair<Acts::ActsVector<nDim>, Acts::Vector3>>
0172   getDistanceAndMomentum(const GeometryContext& gctx,
0173                          const BoundTrackParameters& trkParams,
0174                          const ActsVector<nDim>& vtxPos, State& state) const {
0175     static_assert(nDim == 3 || nDim == 4,
0176                   "Only 3D and 4D vertex positions allowed");
0177     auto res =
0178         getDistanceAndMomentum(gctx, trkParams, {vtxPos.data(), nDim}, state);
0179     if (!res.ok()) {
0180       return res.error();
0181     }
0182     auto& [distance, momentum] = *res;
0183     return std::pair{distance.template head<nDim>(), momentum};
0184   }
0185 
0186   /// @brief Calculates the impact parameters of a track w.r.t. a vertex. The
0187   /// corresponding errors are approximated by summing the variances of the
0188   /// track and the vertex.
0189   ///
0190   /// @param track Track whose impact parameters are calculated
0191   /// @param vtx Vertex corresponding to the track
0192   /// @param gctx The geometry context
0193   /// @param mctx The magnetic field context
0194   /// @param calculateTimeIP If true, the difference in time is computed
0195   Result<ImpactParametersAndSigma> getImpactParameters(
0196       const BoundTrackParameters& track, const Vertex& vtx,
0197       const GeometryContext& gctx, const MagneticFieldContext& mctx,
0198       bool calculateTimeIP = false) const;
0199 
0200   /// @brief Estimates the sign of the 2D and Z lifetime of a given track
0201   /// w.r.t. a vertex and a direction (e.g. a jet direction)
0202   /// by propagating the trajectory state towards the vertex position
0203   /// and computing the scalar product with the direction vector
0204   ///
0205   /// @param track Track to estimate the IP from
0206   /// @param vtx   Vertex the track belongs to
0207   /// @param direction   The direction
0208   /// @param gctx  The geometry context
0209   /// @param mctx  The magnetic field context
0210   ///
0211   /// @return A pair holding the sign for the 2D and Z lifetimes
0212   Result<std::pair<double, double>> getLifetimeSignOfTrack(
0213       const BoundTrackParameters& track, const Vertex& vtx,
0214       const Acts::Vector3& direction, const GeometryContext& gctx,
0215       const MagneticFieldContext& mctx) const;
0216 
0217   /// @brief Estimates the sign of the 3D lifetime of a given track
0218   /// w.r.t. a vertex and a direction (e.g. a jet direction)
0219   ///
0220   /// @param track Track to estimate the IP from
0221   /// @param vtx   Vertex the track belongs to
0222   /// @param direction   The direction
0223   /// @param gctx  The geometry context
0224   /// @param mctx  The magnetic field context
0225   ///
0226   /// @return The value of the 3D lifetime
0227   Result<double> get3DLifetimeSignOfTrack(
0228       const BoundTrackParameters& track, const Vertex& vtx,
0229       const Acts::Vector3& direction, const GeometryContext& gctx,
0230       const MagneticFieldContext& mctx) const;
0231 
0232  private:
0233   Result<std::pair<Acts::Vector4, Acts::Vector3>> getDistanceAndMomentum(
0234       const GeometryContext& gctx, const BoundTrackParameters& trkParams,
0235       Eigen::Map<const ActsDynamicVector> vtxPos, State& state) const;
0236 
0237   Result<double> getVertexCompatibility(
0238       const GeometryContext& gctx, const BoundTrackParameters* trkParams,
0239       Eigen::Map<const ActsDynamicVector> vertexPos) const;
0240 
0241   /// Configuration object
0242   const Config m_cfg;
0243 
0244   /// Logging instance
0245   std::unique_ptr<const Logger> m_logger;
0246 
0247   /// Private access to logging instance
0248   const Logger& logger() const { return *m_logger; }
0249 };
0250 
0251 }  // namespace Acts