Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-06-18 07:46:58

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/Units.hpp"
0013 #include "Acts/Geometry/GeometryContext.hpp"
0014 #include "Acts/Geometry/ProtoLayer.hpp"
0015 #include "Acts/Surfaces/Surface.hpp"
0016 #include "Acts/Surfaces/SurfaceArray.hpp"
0017 #include "Acts/Utilities/AxisDefinitions.hpp"
0018 #include "Acts/Utilities/BinningType.hpp"
0019 #include "Acts/Utilities/IAxis.hpp"
0020 #include "Acts/Utilities/Logger.hpp"
0021 
0022 #include <cmath>
0023 #include <cstddef>
0024 #include <functional>
0025 #include <memory>
0026 #include <numbers>
0027 #include <optional>
0028 #include <utility>
0029 #include <vector>
0030 
0031 namespace ActsTests {
0032 struct SurfaceArrayCreatorFixture;
0033 }
0034 
0035 namespace Acts {
0036 
0037 /// Function type for comparing two surfaces in a given geometry context and
0038 /// axis direction.
0039 /// @param gctx The geometry context for the comparison
0040 /// @param dir The axis direction to consider
0041 /// @param s1 First surface to compare
0042 /// @param s2 Second surface to compare
0043 /// @return True if the surfaces are considered equivalent for binning purposes
0044 using SurfaceMatcher =
0045     std::function<bool(const GeometryContext& gctx, AxisDirection,
0046                        const Surface*, const Surface*)>;
0047 
0048 /// Vector of pointers to constant Surface objects
0049 using SurfaceVector = std::vector<const Surface*>;
0050 /// Matrix (2D vector) of pointers to constant Surface objects
0051 using SurfaceMatrix = std::vector<SurfaceVector>;
0052 
0053 /// @typedef V3Vector
0054 /// Vector of 3D vectors, used for storing collections of 3D points.
0055 using V3Vector = std::vector<Vector3>;
0056 
0057 /// @typedef V3Matrix
0058 /// Matrix (2D vector) of 3D vectors, used for storing grid-like collections of
0059 /// 3D points.
0060 using V3Matrix = std::vector<V3Vector>;
0061 
0062 /// @class SurfaceArrayCreator
0063 ///
0064 /// It is designed create sub surface arrays to be ordered on Surfaces
0065 ///
0066 /// @todo write more documentation on how this is done
0067 class SurfaceArrayCreator {
0068  public:
0069   friend struct ActsTests::SurfaceArrayCreatorFixture;
0070 
0071   /// Configuration options for the surface array creator.
0072   struct Config {
0073     /// Type-erased function which determines whether two surfaces are
0074     /// supposed to be considered equivalent in terms of the binning
0075     SurfaceMatcher surfaceMatcher = SurfaceArrayCreator::isSurfaceEquivalent;
0076 
0077     /// Optimize the binning in phi for disc layers. Reduces the number
0078     /// of bins to the lowest number of non-equivalent phi surfaces
0079     /// of all r-bins. If false, this step is skipped.
0080     bool doPhiBinningOptimization = true;
0081   };
0082 
0083   /// Constructor with default config
0084   ///
0085   /// @param logger logging instance
0086   explicit SurfaceArrayCreator(std::unique_ptr<const Logger> logger =
0087                                    getDefaultLogger("SurfaceArrayCreator",
0088                                                     Logging::INFO))
0089       : m_cfg(Config()), m_logger(std::move(logger)) {}
0090   /// Constructor with explicit config
0091   ///
0092   /// @param cfg Explicit config struct
0093   /// @param logger logging instance
0094   explicit SurfaceArrayCreator(const Config& cfg,
0095                                std::unique_ptr<const Logger> logger =
0096                                    getDefaultLogger("SurfaceArrayCreator",
0097                                                     Logging::INFO))
0098       : m_cfg(cfg), m_logger(std::move(logger)) {}
0099 
0100   /// Destructor
0101   virtual ~SurfaceArrayCreator() = default;
0102 
0103   /// SurfaceArrayCreator interface method
0104   ///
0105   /// - create an array in a cylinder, binned in phi, z when extrema and
0106   /// bin numbers are known
0107   /// @warning This function requires the cylinder aligned with the z-axis
0108   /// @param surfaces is the vector of pointers to sensitive surfaces
0109   /// to be ordered on the cylinder
0110   /// @pre the pointers to the sensitive surfaces in the surfaces vectors all
0111   /// need to be valid, since no check is performed
0112   /// @param [in] gctx The geometry context for this building call
0113   /// @param protoLayerOpt The proto layer containing the layer size
0114   /// @param binsPhi is the number of bins in phi for the surfaces
0115   /// @param binsZ is the number of bin in Z for the surfaces
0116   /// @param transform is the (optional) additional transform applied
0117   /// @param maxNeighborDistance Maximum next neighbor distance to be included in neighbor lookups
0118   ///
0119   /// @return a unique pointer to a new SurfaceArray
0120   SurfaceArray surfaceArrayOnCylinder(
0121       const GeometryContext& gctx,
0122       std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t binsPhi,
0123       std::size_t binsZ, std::optional<ProtoLayer> protoLayerOpt = std::nullopt,
0124       const Transform3& transform = Transform3::Identity(),
0125       std::uint8_t maxNeighborDistance = 1) const;
0126 
0127   /// SurfaceArrayCreator interface method
0128   ///
0129   /// - create an array in a cylinder, binned in phi, z when extrema and bin
0130   /// numbers are unknown - this method goes through the surfaces and finds
0131   /// out the needed information
0132   /// @warning This function requires the cylinder aligned with the z-axis
0133   /// @param surfaces is the vector of pointers to sensitive surfaces
0134   /// to be ordered on the cylinder
0135   /// @pre the pointers to the sensitive surfaces in the surfaces vectors all
0136   /// need to be valid, since no check is performed
0137   /// @param [in] gctx The geometry context for this building call
0138   /// @param protoLayerOpt The proto layer containing the layer size
0139   /// @param bTypePhi the binning type in phi direction (equidistant/arbitrary)
0140   /// @param bTypeZ the binning type in z direction (equidistant/arbitrary)
0141   /// @param transform is the (optional) additional transform applied
0142   /// @param maxNeighborDistance Maximum next neighbor distance to be included in neighbor lookups
0143   ///
0144   /// @return a unique pointer a new SurfaceArray
0145   SurfaceArray surfaceArrayOnCylinder(
0146       const GeometryContext& gctx,
0147       std::vector<std::shared_ptr<const Surface>> surfaces,
0148       BinningType bTypePhi = equidistant, BinningType bTypeZ = equidistant,
0149       std::optional<ProtoLayer> protoLayerOpt = std::nullopt,
0150       const Transform3& transform = Transform3::Identity(),
0151       std::uint8_t maxNeighborDistance = 1) const;
0152 
0153   /// SurfaceArrayCreator interface method
0154   /// - create an array on a disc, binned in r, phi when extrema and
0155   /// bin numbers are known
0156   ///
0157   /// @param surfaces is the vector of pointers to sensitive surfaces
0158   /// to be ordered on the disc
0159   /// @pre the pointers to the sensitive surfaces in the surfaces vectors all
0160   /// need to be valid, since no check is performed
0161   /// @warning This function requires the disc aligned with the z-axis
0162   /// @param [in] gctx The geometry context for this building call
0163   /// @param protoLayerOpt The proto layer containing the layer size
0164   /// @param binsPhi is the number of bins in phi for the surfaces
0165   /// @param binsR is the number of bin in R for the surfaces
0166   /// @param transform is the (optional) additional transform applied
0167   /// @param maxNeighborDistance Maximum next neighbor distance to be included in neighbor lookups
0168   ///
0169   /// @return a unique pointer a new SurfaceArray
0170   SurfaceArray surfaceArrayOnDisc(
0171       const GeometryContext& gctx,
0172       std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t binsR,
0173       std::size_t binsPhi,
0174       std::optional<ProtoLayer> protoLayerOpt = std::nullopt,
0175       const Transform3& transform = Transform3::Identity(),
0176       std::uint8_t maxNeighborDistance = 1) const;
0177 
0178   /// SurfaceArrayCreator interface method
0179   ///
0180   /// - create an array in a cylinder, binned in phi, r when extrema and bin
0181   /// numbers are unknown - this method goes through the surfaces and finds
0182   /// out the needed information
0183   /// @param surfaces is the vector of pointers to sensitive surfaces
0184   /// to be ordered on the disc
0185   /// @pre the pointers to the sensitive surfaces in the surfaces vectors all
0186   /// need to be valid, since no check is performed
0187   /// @warning This function requires the disc aligned with the z-axis
0188   /// @param [in] gctx The geometry context for this building call
0189   /// @param protoLayerOpt The proto layer containing the layer size
0190   /// @param bTypeR the binning type in r direction (equidistant/arbitrary)
0191   /// @param bTypePhi the binning type in phi direction (equidistant/arbitrary)
0192   /// @param transform is the (optional) additional transform applied
0193   /// @param maxNeighborDistance Maximum next neighbor distance to be included in neighbor lookups
0194   ///
0195   /// @return a unique pointer a new SurfaceArray
0196   ///
0197   /// @note If there is more than on R-Ring, number of phi bins
0198   ///       will be set to lowest number of surfaces of any R-ring.
0199   ///       This ignores bTypePhi and produces equidistant binning in phi
0200   SurfaceArray surfaceArrayOnDisc(
0201       const GeometryContext& gctx,
0202       std::vector<std::shared_ptr<const Surface>> surfaces, BinningType bTypeR,
0203       BinningType bTypePhi,
0204       std::optional<ProtoLayer> protoLayerOpt = std::nullopt,
0205       const Transform3& transform = Transform3::Identity(),
0206       std::uint8_t maxNeighborDistance = 1) const;
0207 
0208   /// SurfaceArrayCreator interface method
0209   /// - create an array on a plane
0210   ///
0211   /// @param [in] gctx The geometry context for this building call
0212   /// @param [in] surfaces is the vector of pointers to sensitive surfaces
0213   /// to be ordered on the plane
0214   /// @pre the pointers to the sensitive surfaces in the surfaces vectors all
0215   /// need to be valid, since no check is performed
0216   /// @warning This function requires the plane aligned with either the x-, y-
0217   /// or z-axis
0218   /// @param [in] bins1 is the number of bins in the orthogonal direction to @p
0219   /// aDir
0220   /// @param [in] bins2 is the number of bins in the orthogonal direction to @p
0221   /// aDir
0222   /// @param [in] aDir Direction of the aligned surfaces
0223   /// @param [in] protoLayerOpt Optional @c ProtoLayer instance
0224   /// @param [in] transform is the (optional) additional transform applied
0225   /// @param maxNeighborDistance Maximum next neighbor distance to be included in neighbor lookups
0226   ///
0227   /// @return a unique pointer a new SurfaceArray
0228   SurfaceArray surfaceArrayOnPlane(
0229       const GeometryContext& gctx,
0230       std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t bins1,
0231       std::size_t bins2, AxisDirection aDir,
0232       std::optional<ProtoLayer> protoLayerOpt = std::nullopt,
0233       const Transform3& transform = Transform3::Identity(),
0234       std::uint8_t maxNeighborDistance = 1) const;
0235 
0236   /// Static check function for surface equivalent
0237   ///
0238   /// @param [in] gctx the geometry context for this check
0239   /// @param aDir the axis direction for the binning
0240   /// @param a first surface for checking
0241   /// @param b second surface for checking
0242   /// @return true if surfaces are equivalent for binning purposes
0243   static bool isSurfaceEquivalent(const GeometryContext& gctx,
0244                                   AxisDirection aDir, const Surface* a,
0245                                   const Surface* b) {
0246     using namespace UnitLiterals;
0247     using VectorHelpers::perp;
0248 
0249     if (aDir == AxisDirection::AxisPhi) {
0250       // Take the two binning positions
0251       Vector3 pos1 = a->referencePosition(gctx, AxisDirection::AxisR);
0252       Vector3 pos2 = b->referencePosition(gctx, AxisDirection::AxisR);
0253 
0254       // Project them on the (x, y) plane, where Phi angles are calculated
0255       auto proj1 = pos1.head<2>(), proj2 = pos2.head<2>();
0256 
0257       // Basic dot and cross products identities give us the cosine and sine
0258       // of these angles, time the squared vector norm
0259       auto cos_dPhi_n2 = proj1.dot(proj2);
0260       auto sin_dPhi_n2 = proj1.x() * proj2.y() - proj2.x() * proj1.y();
0261 
0262       // ...so by injecting them into atan2, we get the angle between them
0263       auto dPhi = std::atan2(sin_dPhi_n2, cos_dPhi_n2);
0264       return std::abs(dPhi) < std::numbers::pi / 180.;
0265     }
0266 
0267     if (aDir == AxisDirection::AxisZ) {
0268       return (std::abs(a->referencePosition(gctx, AxisDirection::AxisR).z() -
0269                        b->referencePosition(gctx, AxisDirection::AxisR).z()) <
0270               1_um);
0271     }
0272 
0273     if (aDir == AxisDirection::AxisR) {
0274       return (std::abs(perp(a->referencePosition(gctx, AxisDirection::AxisR)) -
0275                        perp(b->referencePosition(gctx, AxisDirection::AxisR))) <
0276               1_um);
0277     }
0278 
0279     return false;
0280   }
0281 
0282   /// Set logging instance
0283   /// @param logger is the logging instance to be set
0284   void setLogger(std::unique_ptr<const Logger> logger) {
0285     m_logger = std::move(logger);
0286   }
0287 
0288  private:
0289   /// configuration object
0290   Config m_cfg;
0291 
0292   /// Private access to logger
0293   const Logger& logger() const { return *m_logger; }
0294 
0295   std::vector<const Surface*> findKeySurfaces(
0296       const std::vector<const Surface*>& surfaces,
0297       const std::function<bool(const Surface*, const Surface*)>& equal) const;
0298 
0299   std::size_t determineBinCount(const GeometryContext& gctx,
0300                                 const std::vector<const Surface*>& surfaces,
0301                                 AxisDirection aDir) const;
0302 
0303   /// SurfaceArrayCreator internal method
0304   /// Creates a variable @c ProtoAxis from a vector of (unsorted) surfaces with
0305   /// PlanarBounds
0306   /// It loops through the surfaces and finds out the needed information
0307   /// First the surfaces are sorted in the binning direction and the so called
0308   /// "key" surfaces (surfaces with different positions in the binning
0309   /// direction) are extracted. The boundary value between two surfaces is the
0310   /// mean value of the two center position in the binning direction. The
0311   /// first and the last boundaries are calculated from the vertices of the
0312   /// first and last surface.
0313   /// @note currently implemented for phi, r and z bining
0314   /// @todo implement for x,y binning
0315   /// @param [in] gctx the geometry context for this call
0316   /// @param surfaces are the sensitive surfaces to be
0317   /// @param aBoundaryType the AxisBoundaryType for the axis to be created
0318   /// @param aDir the AxisDirection in which direction should be binned
0319   /// (currently possible: AxisPhi, AxisR, AxisZ)
0320   /// @param protoLayer Instance of @c ProtoLayer holding generic layer info
0321   /// @param transform is the (optional) additional transform applied
0322   /// @return Instance of @c ProtoAxis containing determined properties
0323   /// @note This only creates the @c ProtoAxis, this needs to be turned
0324   ///       into an actual @c Axis object to be used
0325   std::unique_ptr<const IAxis> createVariableAxis(
0326       const GeometryContext& gctx, const std::vector<const Surface*>& surfaces,
0327       AxisBoundaryType aBoundaryType, AxisDirection aDir,
0328       const ProtoLayer& protoLayer, Transform3& transform) const;
0329 
0330   /// SurfaceArrayCreator internal method
0331   /// Creates a equidistant @c ProtoAxis when the extrema and the bin number
0332   /// are known.
0333   /// It loops through the surfaces and finds out the needed information
0334   /// First the surfaces are sorted in the binning direction and the so called
0335   /// "key" surfaces (surfaces with different positions in the binning
0336   /// direction) are extracted. The number of key surfaces equals the number
0337   /// of bins. Afterwards the minimum and maximum are calculated by
0338   /// subtracting/adding half of a bin size to the center position (in the
0339   /// binning direction) to the first/last surface.
0340   /// @note currently implemented for phi, r and z bining
0341   /// @todo implement for x,y binning
0342   /// @param [in] gctx the geometry context for this call
0343   /// @param surfaces are the sensitive surfaces to be
0344   /// @param aBoundaryType the AxisBoundaryType for the axis to be created
0345   /// @param aDir the AxisDirection in which direction should be binned
0346   /// (currently possible: AxisPhi, AxisR, AxisZ)
0347   /// @param protoLayer Instance of @c ProtoLayer holding generic layer info
0348   /// @param transform is the (optional) additional transform applied
0349   /// @param nBins Number of bins to use, 0 means determine automatically
0350   /// @return Instance of @c ProtoAxis containing determined properties
0351   /// @note This only creates the @c ProtoAxis, this needs to be turned
0352   ///       into an actual @c Axis object to be used
0353   std::unique_ptr<const IAxis> createEquidistantAxis(
0354       const GeometryContext& gctx, const std::vector<const Surface*>& surfaces,
0355       AxisBoundaryType aBoundaryType, AxisDirection aDir,
0356       const ProtoLayer& protoLayer, Transform3& transform,
0357       std::size_t nBins = 0) const;
0358 
0359   /// logging instance
0360   std::unique_ptr<const Logger> m_logger;
0361 
0362   /// Private helper method to transform the  vertices of surface bounds into
0363   /// global coordinates
0364   /// @param [in] gctx the geometry context for this call
0365   /// @param surface the surface associated with the given vertices
0366   /// @param locVertices a vector of the vertices in local coordinates
0367   /// @return a vector of the vertices in global coordinates
0368   std::vector<Vector3> makeGlobalVertices(
0369       const GeometryContext& gctx, const Surface& surface,
0370       const std::vector<Vector2>& locVertices) const;
0371 };
0372 
0373 }  // namespace Acts