|
|
|||
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
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|