|
|
|||
File indexing completed on 2026-09-24 08:17:44
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 neighborWindow Bounds on the neighbor window the lookup derives 0118 /// from the crossing angle, in bins per grid axis (phi, z) 0119 /// @param overfill Extra cells per direction and axis to fill around each matched cell 0120 /// 0121 /// @return a unique pointer to a new SurfaceArray 0122 SurfaceArray surfaceArrayOnCylinder( 0123 const GeometryContext& gctx, 0124 std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t binsPhi, 0125 std::size_t binsZ, std::optional<ProtoLayer> protoLayerOpt = std::nullopt, 0126 const Transform3& transform = Transform3::Identity(), 0127 SurfaceArray::NeighborWindow neighborWindow = {{0, 0}, {1, 2}}, 0128 std::uint8_t overfill = 0) const; 0129 0130 /// SurfaceArrayCreator interface method 0131 /// 0132 /// - create an array in a cylinder, binned in phi, z when extrema and bin 0133 /// numbers are unknown - this method goes through the surfaces and finds 0134 /// out the needed information 0135 /// @warning This function requires the cylinder aligned with the z-axis 0136 /// @param surfaces is the vector of pointers to sensitive surfaces 0137 /// to be ordered on the cylinder 0138 /// @pre the pointers to the sensitive surfaces in the surfaces vectors all 0139 /// need to be valid, since no check is performed 0140 /// @param [in] gctx The geometry context for this building call 0141 /// @param protoLayerOpt The proto layer containing the layer size 0142 /// @param bTypePhi the binning type in phi direction (equidistant/arbitrary) 0143 /// @param bTypeZ the binning type in z direction (equidistant/arbitrary) 0144 /// @param transform is the (optional) additional transform applied 0145 /// @param neighborWindow Bounds on the neighbor window the lookup derives 0146 /// from the crossing angle, in bins per grid axis (phi, z) 0147 /// @param overfill Extra cells per direction and axis to fill around each matched cell 0148 /// 0149 /// @return a unique pointer a new SurfaceArray 0150 SurfaceArray surfaceArrayOnCylinder( 0151 const GeometryContext& gctx, 0152 std::vector<std::shared_ptr<const Surface>> surfaces, 0153 BinningType bTypePhi = equidistant, BinningType bTypeZ = equidistant, 0154 std::optional<ProtoLayer> protoLayerOpt = std::nullopt, 0155 const Transform3& transform = Transform3::Identity(), 0156 SurfaceArray::NeighborWindow neighborWindow = {{0, 0}, {1, 2}}, 0157 std::uint8_t overfill = 0) const; 0158 0159 /// SurfaceArrayCreator interface method 0160 /// - create an array on a disc, binned in r, phi when extrema and 0161 /// bin numbers are known 0162 /// 0163 /// @param surfaces is the vector of pointers to sensitive surfaces 0164 /// to be ordered on the disc 0165 /// @pre the pointers to the sensitive surfaces in the surfaces vectors all 0166 /// need to be valid, since no check is performed 0167 /// @warning This function requires the disc aligned with the z-axis 0168 /// @param [in] gctx The geometry context for this building call 0169 /// @param protoLayerOpt The proto layer containing the layer size 0170 /// @param binsPhi is the number of bins in phi for the surfaces 0171 /// @param binsR is the number of bin in R for the surfaces 0172 /// @param transform is the (optional) additional transform applied 0173 /// @param neighborWindow Bounds on the neighbor window the lookup derives 0174 /// from the crossing angle, in bins per grid axis (r, phi) 0175 /// @param overfill Extra cells per direction and axis to fill around each matched cell 0176 /// 0177 /// @return a unique pointer a new SurfaceArray 0178 SurfaceArray surfaceArrayOnDisc( 0179 const GeometryContext& gctx, 0180 std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t binsR, 0181 std::size_t binsPhi, 0182 std::optional<ProtoLayer> protoLayerOpt = std::nullopt, 0183 const Transform3& transform = Transform3::Identity(), 0184 SurfaceArray::NeighborWindow neighborWindow = {{0, 0}, {2, 1}}, 0185 std::uint8_t overfill = 0) const; 0186 0187 /// SurfaceArrayCreator interface method 0188 /// 0189 /// - create an array in a cylinder, binned in phi, r when extrema and bin 0190 /// numbers are unknown - this method goes through the surfaces and finds 0191 /// out the needed information 0192 /// @param surfaces is the vector of pointers to sensitive surfaces 0193 /// to be ordered on the disc 0194 /// @pre the pointers to the sensitive surfaces in the surfaces vectors all 0195 /// need to be valid, since no check is performed 0196 /// @warning This function requires the disc aligned with the z-axis 0197 /// @param [in] gctx The geometry context for this building call 0198 /// @param protoLayerOpt The proto layer containing the layer size 0199 /// @param bTypeR the binning type in r direction (equidistant/arbitrary) 0200 /// @param bTypePhi the binning type in phi direction (equidistant/arbitrary) 0201 /// @param transform is the (optional) additional transform applied 0202 /// @param neighborWindow Bounds on the neighbor window the lookup derives 0203 /// from the crossing angle, in bins per grid axis (r, phi) 0204 /// @param overfill Extra cells per direction and axis to fill around each matched cell 0205 /// 0206 /// @return a unique pointer a new SurfaceArray 0207 /// 0208 /// @note If there is more than on R-Ring, number of phi bins 0209 /// will be set to lowest number of surfaces of any R-ring. 0210 /// This ignores bTypePhi and produces equidistant binning in phi 0211 SurfaceArray surfaceArrayOnDisc( 0212 const GeometryContext& gctx, 0213 std::vector<std::shared_ptr<const Surface>> surfaces, BinningType bTypeR, 0214 BinningType bTypePhi, 0215 std::optional<ProtoLayer> protoLayerOpt = std::nullopt, 0216 const Transform3& transform = Transform3::Identity(), 0217 SurfaceArray::NeighborWindow neighborWindow = {{0, 0}, {2, 1}}, 0218 std::uint8_t overfill = 0) const; 0219 0220 /// SurfaceArrayCreator interface method 0221 /// - create an array on a plane 0222 /// 0223 /// @param [in] gctx The geometry context for this building call 0224 /// @param [in] surfaces is the vector of pointers to sensitive surfaces 0225 /// to be ordered on the plane 0226 /// @pre the pointers to the sensitive surfaces in the surfaces vectors all 0227 /// need to be valid, since no check is performed 0228 /// @warning This function requires the plane aligned with either the x-, y- 0229 /// or z-axis 0230 /// @param [in] bins1 is the number of bins in the orthogonal direction to @p 0231 /// aDir 0232 /// @param [in] bins2 is the number of bins in the orthogonal direction to @p 0233 /// aDir 0234 /// @param [in] aDir Direction of the aligned surfaces 0235 /// @param [in] protoLayerOpt Optional @c ProtoLayer instance 0236 /// @param [in] transform is the (optional) additional transform applied 0237 /// @param neighborWindow Bounds on the neighbor window the lookup derives 0238 /// from the crossing angle, in bins per grid axis 0239 /// @param overfill Extra cells per direction and axis to fill around each matched cell 0240 /// 0241 /// @return a unique pointer a new SurfaceArray 0242 SurfaceArray surfaceArrayOnPlane( 0243 const GeometryContext& gctx, 0244 std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t bins1, 0245 std::size_t bins2, AxisDirection aDir, 0246 std::optional<ProtoLayer> protoLayerOpt = std::nullopt, 0247 const Transform3& transform = Transform3::Identity(), 0248 SurfaceArray::NeighborWindow neighborWindow = {{0, 0}, {2, 2}}, 0249 std::uint8_t overfill = 0) const; 0250 0251 /// Static check function for surface equivalent 0252 /// 0253 /// @param [in] gctx the geometry context for this check 0254 /// @param aDir the axis direction for the binning 0255 /// @param a first surface for checking 0256 /// @param b second surface for checking 0257 /// @return true if surfaces are equivalent for binning purposes 0258 static bool isSurfaceEquivalent(const GeometryContext& gctx, 0259 AxisDirection aDir, const Surface* a, 0260 const Surface* b) { 0261 using namespace UnitLiterals; 0262 using VectorHelpers::perp; 0263 0264 if (aDir == AxisDirection::AxisPhi) { 0265 // Take the two binning positions 0266 Vector3 pos1 = a->referencePosition(gctx, AxisDirection::AxisR); 0267 Vector3 pos2 = b->referencePosition(gctx, AxisDirection::AxisR); 0268 0269 // Project them on the (x, y) plane, where Phi angles are calculated 0270 auto proj1 = pos1.head<2>(), proj2 = pos2.head<2>(); 0271 0272 // Basic dot and cross products identities give us the cosine and sine 0273 // of these angles, time the squared vector norm 0274 auto cos_dPhi_n2 = proj1.dot(proj2); 0275 auto sin_dPhi_n2 = proj1.x() * proj2.y() - proj2.x() * proj1.y(); 0276 0277 // ...so by injecting them into atan2, we get the angle between them 0278 auto dPhi = std::atan2(sin_dPhi_n2, cos_dPhi_n2); 0279 return std::abs(dPhi) < std::numbers::pi / 180.; 0280 } 0281 0282 if (aDir == AxisDirection::AxisZ) { 0283 return (std::abs(a->referencePosition(gctx, AxisDirection::AxisR).z() - 0284 b->referencePosition(gctx, AxisDirection::AxisR).z()) < 0285 1_um); 0286 } 0287 0288 if (aDir == AxisDirection::AxisR) { 0289 return (std::abs(perp(a->referencePosition(gctx, AxisDirection::AxisR)) - 0290 perp(b->referencePosition(gctx, AxisDirection::AxisR))) < 0291 1_um); 0292 } 0293 0294 return false; 0295 } 0296 0297 /// Set logging instance 0298 /// @param logger is the logging instance to be set 0299 void setLogger(std::unique_ptr<const Logger> logger) { 0300 m_logger = std::move(logger); 0301 } 0302 0303 /// Determine the number of bins for a binning direction from the number of 0304 /// distinct module positions (i.e. one bin per module). Public so navigation 0305 /// policies can size their surface-array grids relative to the module count. 0306 /// @param gctx the geometry context 0307 /// @param surfaces the surfaces to analyse 0308 /// @param aDir the binning direction 0309 /// @return the number of distinct module positions along @p aDir 0310 std::size_t determineBinCount(const GeometryContext& gctx, 0311 const std::vector<const Surface*>& surfaces, 0312 AxisDirection aDir) const; 0313 0314 private: 0315 /// configuration object 0316 Config m_cfg; 0317 0318 /// Private access to logger 0319 const Logger& logger() const { return *m_logger; } 0320 0321 std::vector<const Surface*> findKeySurfaces( 0322 const std::vector<const Surface*>& surfaces, 0323 const std::function<bool(const Surface*, const Surface*)>& equal) const; 0324 0325 /// SurfaceArrayCreator internal method 0326 /// Creates a variable axis from a vector of (unsorted) surfaces with 0327 /// PlanarBounds 0328 /// It loops through the surfaces and finds out the needed information 0329 /// First the surfaces are sorted in the binning direction and the so called 0330 /// "key" surfaces (surfaces with different positions in the binning 0331 /// direction) are extracted. The boundary value between two surfaces is the 0332 /// mean value of the two center position in the binning direction. The 0333 /// first and the last boundaries are calculated from the vertices of the 0334 /// first and last surface. 0335 /// @note currently implemented for phi, r and z bining 0336 /// @todo implement for x,y binning 0337 /// @param [in] gctx the geometry context for this call 0338 /// @param surfaces are the sensitive surfaces to be 0339 /// @param aBoundaryType the AxisBoundaryType for the axis to be created 0340 /// @param aDir the AxisDirection in which direction should be binned 0341 /// (currently possible: AxisPhi, AxisR, AxisZ) 0342 /// @param protoLayer Instance of @c ProtoLayer holding generic layer info 0343 /// @param transform is the (optional) additional transform applied 0344 /// @return Type-erased @c IAxis containing the determined properties 0345 std::unique_ptr<const IAxis> createVariableAxis( 0346 const GeometryContext& gctx, const std::vector<const Surface*>& surfaces, 0347 AxisBoundaryType aBoundaryType, AxisDirection aDir, 0348 const ProtoLayer& protoLayer, Transform3& transform) const; 0349 0350 /// SurfaceArrayCreator internal method 0351 /// Creates a equidistant axis when the extrema and the bin number 0352 /// are known. 0353 /// It loops through the surfaces and finds out the needed information 0354 /// First the surfaces are sorted in the binning direction and the so called 0355 /// "key" surfaces (surfaces with different positions in the binning 0356 /// direction) are extracted. The number of key surfaces equals the number 0357 /// of bins. Afterwards the minimum and maximum are calculated by 0358 /// subtracting/adding half of a bin size to the center position (in the 0359 /// binning direction) to the first/last surface. 0360 /// @note currently implemented for phi, r and z bining 0361 /// @todo implement for x,y binning 0362 /// @param [in] gctx the geometry context for this call 0363 /// @param surfaces are the sensitive surfaces to be 0364 /// @param aBoundaryType the AxisBoundaryType for the axis to be created 0365 /// @param aDir the AxisDirection in which direction should be binned 0366 /// (currently possible: AxisPhi, AxisR, AxisZ) 0367 /// @param protoLayer Instance of @c ProtoLayer holding generic layer info 0368 /// @param transform is the (optional) additional transform applied 0369 /// @param nBins Number of bins to use, 0 means determine automatically 0370 /// @return Type-erased @c IAxis containing the determined properties 0371 std::unique_ptr<const IAxis> createEquidistantAxis( 0372 const GeometryContext& gctx, const std::vector<const Surface*>& surfaces, 0373 AxisBoundaryType aBoundaryType, AxisDirection aDir, 0374 const ProtoLayer& protoLayer, Transform3& transform, 0375 std::size_t nBins = 0) const; 0376 0377 /// logging instance 0378 std::unique_ptr<const Logger> m_logger; 0379 0380 /// Private helper method to transform the vertices of surface bounds into 0381 /// global coordinates 0382 /// @param [in] gctx the geometry context for this call 0383 /// @param surface the surface associated with the given vertices 0384 /// @param locVertices a vector of the vertices in local coordinates 0385 /// @return a vector of the vertices in global coordinates 0386 std::vector<Vector3> makeGlobalVertices( 0387 const GeometryContext& gctx, const Surface& surface, 0388 const std::vector<Vector2>& locVertices) const; 0389 }; 0390 0391 } // namespace Acts
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|