Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-06-05 08:29:40

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