Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:00

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2019-2023 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/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     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     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   ImpactPointEstimator(const Config& cfg,
0086                        std::unique_ptr<const Logger> logger = getDefaultLogger(
0087                            "ImpactPointEstimator", Logging::INFO))
0088       : m_cfg(cfg), m_logger(std::move(logger)) {}
0089 
0090   /// @brief Copy constructor to clone logger (class owns a unique pointer to it,
0091   /// which can't be copied)
0092   ///
0093   /// @param other Impact point estimator to be cloned
0094   ImpactPointEstimator(const ImpactPointEstimator& other)
0095       : m_cfg(other.m_cfg), m_logger(other.logger().clone()) {}
0096 
0097   /// Move constructor for impact point estimator
0098   ImpactPointEstimator(ImpactPointEstimator&&) = default;
0099 
0100   /// @brief Calculates 3D distance between a track and a vertex
0101   ///
0102   /// @param gctx The geometry context
0103   /// @param trkParams Track parameters
0104   /// @param vtxPos 3D position to calculate the distance to
0105   /// @param state The state object
0106   ///
0107   /// @return Distance
0108   Result<double> calculateDistance(const GeometryContext& gctx,
0109                                    const BoundTrackParameters& trkParams,
0110                                    const Vector3& vtxPos, State& state) const;
0111 
0112   /// @brief Estimates the track parameters at the 3D PCA (i.e., a point of
0113   /// minimal 3D distance) to a vertex. The track parameters are defined wrt a
0114   /// reference plane that has its origin at the vertex position and whose
0115   /// z-axis points in the direction of the track momentum. The plane's x-axis
0116   /// points approximately from the vertex to the 3D PCA (it is only approximate
0117   /// because we force it to be orthogonal to the z-axis). The y-axis is
0118   /// calculated as a cross product between x- and z-axis.
0119   ///
0120   /// @param gctx The geometry context
0121   /// @param mctx The magnetic field context
0122   /// @param trkParams Track parameters
0123   /// @param vtxPos Reference position (vertex)
0124   /// @param state The state object
0125   ///
0126   /// @return Track parameters at the 3D PCA
0127   Result<BoundTrackParameters> estimate3DImpactParameters(
0128       const GeometryContext& gctx, const Acts::MagneticFieldContext& mctx,
0129       const BoundTrackParameters& trkParams, const Vector3& vtxPos,
0130       State& state) const;
0131 
0132   /// @brief Estimates the compatibility of a track to a vertex based on their
0133   /// 3D (if nDim = 3) or 4D (if nDim = 4) distance and the track covariance.
0134   /// @note Confusingly, a *smaller* compatibility means that a track is *more*
0135   /// compatible.
0136   ///
0137   /// @tparam nDim Number of dimensions used to compute compatibility
0138   /// @note If @p nDim = 3 we only consider spatial dimensions; if nDim = 4, we
0139   ///       also consider time. Other values are not allowed.
0140   /// @param gctx The Geometry context
0141   /// @param trkParams Track parameters at point of closest
0142   /// approach in 3D as retrieved by estimate3DImpactParameters
0143   /// @param vertexPos The vertex position
0144   ///
0145   /// @return The compatibility value
0146   template <int nDim>
0147   Result<double> getVertexCompatibility(
0148       const GeometryContext& gctx, const BoundTrackParameters* trkParams,
0149       const ActsVector<nDim>& vertexPos) const {
0150     static_assert(nDim == 3 || nDim == 4,
0151                   "Only 3D and 4D vertex positions allowed");
0152     return getVertexCompatibility(gctx, trkParams, {vertexPos.data(), nDim});
0153   }
0154 
0155   /// @brief Calculate the distance between a track and a vertex by finding the
0156   /// corresponding 3D PCA. Returns also the momentum direction at the 3D PCA.
0157   /// The template parameter nDim determines whether we calculate the 3D
0158   /// distance (nDim = 3) or the 4D distance (nDim = 4) to the 3D PCA.
0159   /// @note For straight tracks we use an analytical solution; for helical
0160   /// tracks we use the Newton method.
0161   ///
0162   /// @tparam nDim Number of dimensions used to compute compatibility
0163   /// @note If @p nDim = 3 we only consider spatial dimensions; if nDim = 4, we
0164   ///       also consider time. Other values are not allowed.
0165   /// @param gctx Geometry context
0166   /// @param trkParams Track parameters
0167   /// @param vtxPos Vertex position
0168   /// @param state The state object
0169   template <int nDim>
0170   Result<std::pair<Acts::ActsVector<nDim>, Acts::Vector3>>
0171   getDistanceAndMomentum(const GeometryContext& gctx,
0172                          const BoundTrackParameters& trkParams,
0173                          const ActsVector<nDim>& vtxPos, State& state) const {
0174     static_assert(nDim == 3 || nDim == 4,
0175                   "Only 3D and 4D vertex positions allowed");
0176     auto res =
0177         getDistanceAndMomentum(gctx, trkParams, {vtxPos.data(), nDim}, state);
0178     if (!res.ok()) {
0179       return res.error();
0180     }
0181     auto& [distance, momentum] = *res;
0182     return std::pair{distance.template head<nDim>(), momentum};
0183   }
0184 
0185   /// @brief Calculates the impact parameters of a track w.r.t. a vertex. The
0186   /// corresponding errors are approximated by summing the variances of the
0187   /// track and the vertex.
0188   ///
0189   /// @param track Track whose impact parameters are calculated
0190   /// @param vtx Vertex corresponding to the track
0191   /// @param gctx The geometry context
0192   /// @param mctx The magnetic field context
0193   /// @param calculateTimeIP If true, the difference in time is computed
0194   Result<ImpactParametersAndSigma> getImpactParameters(
0195       const BoundTrackParameters& track, const Vertex& vtx,
0196       const GeometryContext& gctx, const MagneticFieldContext& mctx,
0197       bool calculateTimeIP = false) const;
0198 
0199   /// @brief Estimates the sign of the 2D and Z lifetime of a given track
0200   /// w.r.t. a vertex and a direction (e.g. a jet direction)
0201   /// by propagating the trajectory state towards the vertex position
0202   /// and computing the scalar product with the direction vector
0203   ///
0204   /// @param track Track to estimate the IP from
0205   /// @param vtx   Vertex the track belongs to
0206   /// @param direction   The direction
0207   /// @param gctx  The geometry context
0208   /// @param mctx  The magnetic field context
0209   ///
0210   /// @return A pair holding the sign for the 2D and Z lifetimes
0211   Result<std::pair<double, double>> getLifetimeSignOfTrack(
0212       const BoundTrackParameters& track, const Vertex& vtx,
0213       const Acts::Vector3& direction, const GeometryContext& gctx,
0214       const MagneticFieldContext& mctx) const;
0215 
0216   /// @brief Estimates the sign of the 3D lifetime of a given track
0217   /// w.r.t. a vertex and a direction (e.g. a jet direction)
0218   ///
0219   /// @param track Track to estimate the IP from
0220   /// @param vtx   Vertex the track belongs to
0221   /// @param direction   The direction
0222   /// @param gctx  The geometry context
0223   /// @param mctx  The magnetic field context
0224   ///
0225   /// @return The value of the 3D lifetime
0226   Result<double> get3DLifetimeSignOfTrack(
0227       const BoundTrackParameters& track, const Vertex& vtx,
0228       const Acts::Vector3& direction, const GeometryContext& gctx,
0229       const MagneticFieldContext& mctx) const;
0230 
0231  private:
0232   Result<std::pair<Acts::Vector4, Acts::Vector3>> getDistanceAndMomentum(
0233       const GeometryContext& gctx, const BoundTrackParameters& trkParams,
0234       Eigen::Map<const ActsDynamicVector> vtxPos, State& state) const;
0235 
0236   Result<double> getVertexCompatibility(
0237       const GeometryContext& gctx, const BoundTrackParameters* trkParams,
0238       Eigen::Map<const ActsDynamicVector> vertexPos) const;
0239 
0240   /// Configuration object
0241   const Config m_cfg;
0242 
0243   /// Logging instance
0244   std::unique_ptr<const Logger> m_logger;
0245 
0246   /// Private access to logging instance
0247   const Logger& logger() const { return *m_logger; }
0248 };
0249 
0250 }  // namespace Acts