Back to home page

EIC code displayed by LXR

 
 

    


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

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