Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:11:50

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/Definitions/Tolerance.hpp"
0013 #include "Acts/Surfaces/DiscBounds.hpp"
0014 #include "Acts/Surfaces/SurfaceBounds.hpp"
0015 
0016 #include <array>
0017 #include <cmath>
0018 #include <iosfwd>
0019 #include <numbers>
0020 #include <vector>
0021 
0022 namespace Acts {
0023 
0024 /// @brief Class that implements a (potentially asymmetric) bounds with
0025 /// difference between surface bound center and surface coordinate center
0026 ///
0027 /// These bounds combine two different systems:
0028 ///  * module system : radial bounds centred on the moduleOrigin
0029 ///  * strip system : phi bounds centred on the stripOrigin
0030 ///
0031 /// The measurement will be done in the strip system, with r/phi local
0032 /// coordinates.
0033 ///
0034 class AnnulusBounds : public DiscBounds {
0035  public:
0036   enum BoundValues : int {
0037     eMinR = 0,
0038     eMaxR = 1,
0039     eMinPhiRel = 2,
0040     eMaxPhiRel = 3,
0041     eAveragePhi = 4,
0042     eOriginX = 5,
0043     eOriginY = 6,
0044     eSize = 7
0045   };
0046 
0047   /// @brief Default constructor from parameters
0048   /// @param minR The inner radius of the annulus
0049   /// @param maxR The outer radius of the annulus
0050   /// @param minPhiRel The minimum phi relative to average phi
0051   /// @param maxPhiRel The maximum phi relative to average phi
0052   /// @param moduleOrigin The origin of the module in the strip frame
0053   /// @param avgPhi The average phi value
0054   /// @note For @c morigin you need to actually calculate the cartesian
0055   /// offset
0056   explicit AnnulusBounds(double minR, double maxR, double minPhiRel,
0057                          double maxPhiRel, const Vector2& moduleOrigin = {0, 0},
0058                          double avgPhi = 0) noexcept(false)
0059       : AnnulusBounds({minR, maxR, minPhiRel, maxPhiRel, avgPhi,
0060                        moduleOrigin.x(), moduleOrigin.y()}) {}
0061 
0062   /// Constructor - from fixed size array
0063   ///
0064   /// @param values The bound values stored in a fixed size array
0065   explicit AnnulusBounds(const std::array<double, eSize>& values) noexcept(
0066       false);
0067 
0068   BoundsType type() const final { return eAnnulus; }
0069 
0070   /// @copydoc SurfaceBounds::isCartesian
0071   bool isCartesian() const final { return false; }
0072 
0073   /// @copydoc SurfaceBounds::boundToCartesianJacobian
0074   SquareMatrix2 boundToCartesianJacobian(const Vector2& lposition) const final;
0075 
0076   /// @copydoc SurfaceBounds::boundToCartesianMetric
0077   SquareMatrix2 boundToCartesianMetric(const Vector2& lposition) const final;
0078 
0079   /// Return the bound values as dynamically sized vector
0080   /// @return this returns a copy of the internal values
0081   std::vector<double> values() const final;
0082 
0083   /// @copydoc SurfaceBounds::inside
0084   bool inside(const Vector2& lposition) const final;
0085 
0086   /// @copydoc SurfaceBounds::closestPoint
0087   Vector2 closestPoint(const Vector2& lposition,
0088                        const SquareMatrix2& metric) const final;
0089 
0090   using SurfaceBounds::inside;
0091 
0092   /// @copydoc SurfaceBounds::center
0093   /// @note For AnnulusBounds: returns pre-calculated center from corner vertices in strip polar coordinates (r, phi), accounting for average phi rotation
0094   Vector2 center() const final;
0095 
0096   /// Outstream operator
0097   /// @param sl is the ostream to be dumped into
0098   std::ostream& toStream(std::ostream& sl) const final;
0099 
0100   /// Access to the bound values
0101   /// @param bValue the class nested enum for the array access
0102   double get(BoundValues bValue) const { return m_values[bValue]; }
0103 
0104   /// @brief Returns the right angular edge of the module
0105   /// @return The right side angle
0106   double phiMin() const { return get(eMinPhiRel) + get(eAveragePhi); }
0107 
0108   /// @brief Returns the left angular edge of the module
0109   /// @return The left side angle
0110   double phiMax() const { return get(eMaxPhiRel) + get(eAveragePhi); }
0111 
0112   /// Returns true for full phi coverage
0113   bool coversFullAzimuth() const final {
0114     return (std::abs((get(eMinPhiRel) - get(eMaxPhiRel)) - std::numbers::pi) <
0115             s_onSurfaceTolerance);
0116   }
0117 
0118   /// Checks if this is inside the radial coverage
0119   /// given the a tolerance
0120   bool insideRadialBounds(double R, double tolerance = 0.) const final {
0121     return ((R + tolerance) > get(eMinR) && (R - tolerance) < get(eMaxR));
0122   }
0123 
0124   /// Return a reference radius for binning
0125   double binningValueR() const final { return 0.5 * (get(eMinR) + get(eMaxR)); }
0126 
0127   /// Return a reference radius for binning
0128   double binningValuePhi() const final { return get(eAveragePhi); }
0129 
0130   /// @brief Returns moduleOrigin, but rotated out, so @c averagePhi is already
0131   /// considered. The module origin needs to consider the rotation introduced by
0132   /// @c averagePhi
0133   /// @return The origin of the local frame
0134   Vector2 moduleOrigin() const;
0135 
0136   /// This method returns the four corners of the bounds in polar coordinates
0137   /// Starting from the upper right (max R, pos locX) and proceeding clock-wise
0138   /// i.e. (max R; pos locX), (min R; pos locX), (min R; neg loc X), (max R: neg
0139   /// locX)
0140   std::vector<Vector2> corners() const;
0141 
0142   /// This method returns the xy coordinates of the four corners of the
0143   /// bounds in module coordinates (in x/y), and if quarterSegments is bigger or
0144   /// equal to 0, the curved part of the segment is included and approximated
0145   /// by the corresponding number of segments.
0146   ///
0147   /// Starting from the upper right (max R, pos locX) and proceeding clock-wise
0148   /// i.e. (max R; pos locX), (min R; pos locX), (min R; neg loc X), (max R: neg
0149   /// locX)
0150   ///
0151   /// @param quarterSegments the number of segments used to approximate
0152   /// a quarter of a circle
0153   ///
0154   /// @return vector for vertices in 2D
0155   std::vector<Vector2> vertices(
0156       unsigned int quarterSegments = 2u) const override;
0157 
0158   /// This method returns inner radius
0159   double rMin() const final { return get(eMinR); }
0160 
0161   /// This method returns outer radius
0162   double rMax() const final { return get(eMaxR); }
0163 
0164  private:
0165   std::array<double, eSize> m_values;
0166 
0167   // @TODO: Does this need to be in bound values?
0168   Vector2 m_moduleOrigin{
0169       Vector2::Zero()};  ///< The origin of the module in the strip frame
0170   Vector2 m_shiftXY{Vector2::Zero()};  // == -m_moduleOrigin
0171   Vector2 m_shiftPC{Vector2::Zero()};
0172   Transform2 m_rotationStripPC{Transform2::Identity()};  ///< Rotation to strip
0173   Transform2 m_translation{Transform2::Identity()};  ///< Translation to strip
0174 
0175   // Vectors needed for inside checking
0176   Vector2 m_outLeftStripPC{Vector2::Zero()};
0177   Vector2 m_inLeftStripPC{Vector2::Zero()};
0178   Vector2 m_outRightStripPC{Vector2::Zero()};
0179   Vector2 m_inRightStripPC{Vector2::Zero()};
0180 
0181   Vector2 m_outLeftModulePC{Vector2::Zero()};
0182   Vector2 m_inLeftModulePC{Vector2::Zero()};
0183   Vector2 m_outRightModulePC{Vector2::Zero()};
0184   Vector2 m_inRightModulePC{Vector2::Zero()};
0185 
0186   Vector2 m_outLeftStripXY{Vector2::Zero()};
0187   Vector2 m_inLeftStripXY{Vector2::Zero()};
0188   Vector2 m_outRightStripXY{Vector2::Zero()};
0189   Vector2 m_inRightStripXY{Vector2::Zero()};
0190 
0191   /// Pre-calculated center point (average of vertices)
0192   Vector2 m_center{Vector2::Zero()};
0193 
0194   /// Check the input values for consistency, will throw a logic_exception
0195   /// if consistency is not given
0196   void checkConsistency() noexcept(false);
0197 
0198   /// Transform the strip cartesian into the module polar system
0199   ///
0200   /// @param vStripXY the position in the cartesian strip system
0201   /// @return the position in the module polar coordinate system
0202   Vector2 stripXYToModulePC(const Vector2& vStripXY) const;
0203 
0204   Vector2 stripPCToModulePC(const Vector2& vStripPC) const;
0205 
0206   Vector2 modulePCToStripPC(const Vector2& vModulePC) const;
0207 
0208   SquareMatrix2 stripPCToModulePCJacobian(
0209       const Vector2& lpositionRotated) const;
0210 };
0211 
0212 }  // namespace Acts