Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:11:03

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 
0013 #include <optional>
0014 #include <variant>
0015 
0016 namespace Acts {
0017 
0018 /// @brief Variant-like type to capture different types of boundary tolerances
0019 ///
0020 /// Since our track hypothesis comes with uncertainties, we sometimes need to
0021 /// check if the track is not just within the boundary of the surface but also
0022 /// within a certain tolerance. This class captures different parameterizations
0023 /// of such tolerances. The surface class will then use these tolerances to
0024 /// check if a ray is within the boundary+tolerance of the surface.
0025 ///
0026 /// Different types of boundary tolerances implemented:
0027 /// - Infinite: Infinite tolerance i.e. no boundary check will be performed.
0028 /// - None: No tolerance i.e. exact boundary check will be performed.
0029 /// - AbsoluteBound: Absolute tolerance in bound coordinates.
0030 ///   The tolerance is defined as a pair of absolute values for the bound
0031 ///   coordinates. Only if both coordinates are within the tolerance, the
0032 ///   boundary check is considered as passed.
0033 /// - AbsoluteCartesian: Absolute tolerance in Cartesian coordinates.
0034 ///   The tolerance is defined as a pair of absolute values for the Cartesian
0035 ///   coordinates. The transformation to Cartesian coordinates can be done via
0036 ///   the Jacobian for small distances. Only if both coordinates are within
0037 ///   the tolerance, the boundary check is considered as passed.
0038 /// - AbsoluteEuclidean: Absolute tolerance in Euclidean distance.
0039 ///   The tolerance is defined as a single absolute value for the Euclidean
0040 ///   distance. The Euclidean distance can be calculated via the local bound
0041 ///   Jacobian and the bound coordinate residual. If the distance is within
0042 ///   the tolerance, the boundary check is considered as passed.
0043 /// - Chi2Bound: Chi2 tolerance in bound coordinates.
0044 ///   The tolerance is defined as a maximum chi2 value and a weight matrix,
0045 ///   which is the inverse of the bound covariance matrix. The chi2 value is
0046 ///   calculated from the bound coordinates residual and the weight matrix.
0047 ///   If the chi2 value is below the maximum chi2 value, the boundary check
0048 ///   is considered as passed.
0049 ///
0050 /// The bound coordinates residual is defined as the difference between the
0051 /// point checked and the closest point on the boundary. The Jacobian is the
0052 /// derivative of the bound coordinates with respect to the Cartesian
0053 /// coordinates.
0054 ///
0055 class BoundaryTolerance {
0056  public:
0057   struct InfiniteParams {};
0058 
0059   struct NoneParams {};
0060 
0061   struct AbsoluteBoundParams {
0062     double tolerance0{};
0063     double tolerance1{};
0064 
0065     AbsoluteBoundParams() = default;
0066     AbsoluteBoundParams(double tolerance0_, double tolerance1_)
0067         : tolerance0(tolerance0_), tolerance1(tolerance1_) {
0068       if (tolerance0 < 0 || tolerance1 < 0) {
0069         throw std::invalid_argument(
0070             "AbsoluteBound: Tolerance must be non-negative");
0071       }
0072     }
0073   };
0074 
0075   struct AbsoluteCartesianParams {
0076     double tolerance0{};
0077     double tolerance1{};
0078 
0079     AbsoluteCartesianParams() = default;
0080     AbsoluteCartesianParams(double tolerance0_, double tolerance1_)
0081         : tolerance0(tolerance0_), tolerance1(tolerance1_) {
0082       if (tolerance0 < 0 || tolerance1 < 0) {
0083         throw std::invalid_argument(
0084             "AbsoluteCartesian: Tolerance must be non-negative");
0085       }
0086       if ((tolerance0 == 0) != (tolerance1 == 0)) {
0087         throw std::invalid_argument(
0088             "AbsoluteCartesian: Both tolerances must be zero or non-zero");
0089       }
0090     }
0091   };
0092 
0093   struct AbsoluteEuclideanParams {
0094     double tolerance{};
0095 
0096     AbsoluteEuclideanParams() = default;
0097     explicit AbsoluteEuclideanParams(double tolerance_)
0098         : tolerance(tolerance_) {}
0099   };
0100 
0101   struct Chi2BoundParams {
0102     double maxChi2{};
0103     SquareMatrix2 weight = SquareMatrix2::Identity();
0104 
0105     Chi2BoundParams() = default;
0106     Chi2BoundParams(const SquareMatrix2& weight_, double maxChi2_)
0107         : maxChi2(maxChi2_), weight(weight_) {}
0108   };
0109 
0110  private:
0111   /// Underlying variant type
0112   using Variant = std::variant<InfiniteParams, NoneParams, AbsoluteBoundParams,
0113                                AbsoluteCartesianParams, AbsoluteEuclideanParams,
0114                                Chi2BoundParams>;
0115 
0116   /// Construct from variant
0117   explicit BoundaryTolerance(Variant variant);
0118 
0119  public:
0120   /// Infinite tolerance i.e. no boundary check
0121   static auto Infinite() { return BoundaryTolerance{InfiniteParams{}}; }
0122 
0123   /// No tolerance i.e. exact boundary check
0124   static auto None() { return BoundaryTolerance{NoneParams{}}; }
0125 
0126   /// Absolute tolerance in bound coordinates
0127   static auto AbsoluteBound(double tolerance0, double tolerance1) {
0128     return BoundaryTolerance{AbsoluteBoundParams{tolerance0, tolerance1}};
0129   }
0130 
0131   /// Absolute tolerance in Cartesian coordinates
0132   static auto AbsoluteCartesian(double tolerance0, double tolerance1) {
0133     return BoundaryTolerance{AbsoluteCartesianParams{tolerance0, tolerance1}};
0134   }
0135 
0136   /// Absolute tolerance in Euclidean distance
0137   static auto AbsoluteEuclidean(double tolerance) {
0138     return BoundaryTolerance{AbsoluteEuclideanParams{tolerance}};
0139   }
0140 
0141   /// Chi2 tolerance in bound coordinates
0142   static auto Chi2Bound(const SquareMatrix2& weight, double maxChi2) {
0143     return BoundaryTolerance{Chi2BoundParams{weight, maxChi2}};
0144   }
0145 
0146   enum class ToleranceMode {
0147     Extend,  // Extend the boundary
0148     None,    // No tolerance
0149     Shrink   // Shrink the boundary
0150   };
0151 
0152   /// Check if the tolerance is infinite.
0153   bool isInfinite() const;
0154   /// Check if the is no tolerance.
0155   bool isNone() const;
0156   /// Check if the tolerance is absolute with bound coordinates.
0157   bool hasAbsoluteBound(bool isCartesian = false) const;
0158   /// Check if the tolerance is absolute with Cartesian coordinates.
0159   bool hasAbsoluteCartesian() const;
0160   /// Check if the tolerance is absolute with Euclidean distance.
0161   bool hasAbsoluteEuclidean() const;
0162   /// Check if the tolerance is chi2 with bound coordinates.
0163   bool hasChi2Bound() const;
0164 
0165   /// Check if any tolerance is set.
0166   ToleranceMode toleranceMode() const;
0167 
0168   /// Get the tolerance as absolute bound.
0169   AbsoluteBoundParams asAbsoluteBound(bool isCartesian = false) const;
0170   /// Get the tolerance as absolute Cartesian.
0171   const AbsoluteCartesianParams& asAbsoluteCartesian() const;
0172   /// Get the tolerance as absolute Euclidean.
0173   const AbsoluteEuclideanParams& asAbsoluteEuclidean() const;
0174   /// Get the tolerance as chi2 bound.
0175   const Chi2BoundParams& asChi2Bound() const;
0176 
0177   /// Get the tolerance as absolute bound if possible.
0178   std::optional<AbsoluteBoundParams> asAbsoluteBoundOpt(
0179       bool isCartesian = false) const;
0180 
0181   /// Check if the distance is tolerated.
0182   bool isTolerated(const Vector2& distance,
0183                    const std::optional<SquareMatrix2>& jacobianOpt) const;
0184 
0185   /// Check if there is a metric assigned with this tolerance.
0186   bool hasMetric(bool hasJacobian) const;
0187 
0188   /// Get the metric for the tolerance.
0189   SquareMatrix2 getMetric(const std::optional<SquareMatrix2>& jacobian) const;
0190 
0191  private:
0192   Variant m_variant;
0193 
0194   /// Check if the boundary check is of a specific type.
0195   template <typename T>
0196   bool holdsVariant() const {
0197     return std::holds_alternative<T>(m_variant);
0198   }
0199 
0200   /// Get the specific underlying type.
0201   template <typename T>
0202   const T& getVariant() const {
0203     return std::get<T>(m_variant);
0204   }
0205 
0206   template <typename T>
0207   const T* getVariantPtr() const {
0208     return holdsVariant<T>() ? &getVariant<T>() : nullptr;
0209   }
0210 };
0211 
0212 }  // namespace Acts