Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-23 07:34:36

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 #include "Acts/Geometry/LayerCreator.hpp"
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Geometry/CylinderLayer.hpp"
0013 #include "Acts/Geometry/DiscLayer.hpp"
0014 #include "Acts/Geometry/Extent.hpp"
0015 #include "Acts/Geometry/Layer.hpp"
0016 #include "Acts/Geometry/PlaneLayer.hpp"
0017 #include "Acts/Geometry/ProtoLayer.hpp"
0018 #include "Acts/Geometry/SurfaceArrayCreator.hpp"
0019 #include "Acts/Surfaces/CylinderBounds.hpp"
0020 #include "Acts/Surfaces/RadialBounds.hpp"
0021 #include "Acts/Surfaces/RectangleBounds.hpp"
0022 #include "Acts/Surfaces/Surface.hpp"
0023 #include "Acts/Utilities/Diagnostics.hpp"
0024 
0025 #include <algorithm>
0026 #include <iterator>
0027 #include <ostream>
0028 #include <set>
0029 #include <utility>
0030 
0031 namespace Acts {
0032 
0033 using VectorHelpers::perp;
0034 using VectorHelpers::phi;
0035 
0036 LayerCreator::LayerCreator(const LayerCreator::Config& lcConfig,
0037                            std::unique_ptr<const Logger> logger)
0038     : m_cfg(lcConfig), m_logger(std::move(logger)) {}
0039 
0040 void LayerCreator::setConfiguration(const LayerCreator::Config& lcConfig) {
0041   // @todo check consistency
0042   // copy the configuration
0043   m_cfg = lcConfig;
0044 }
0045 
0046 void LayerCreator::setLogger(std::unique_ptr<const Logger> newLogger) {
0047   m_logger = std::move(newLogger);
0048 }
0049 
0050 MutableLayerPtr LayerCreator::cylinderLayer(
0051     const GeometryContext& gctx,
0052     std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t binsPhi,
0053     std::size_t binsZ, std::optional<ProtoLayer> _protoLayer,
0054     const Transform3& transform, std::unique_ptr<ApproachDescriptor> ad,
0055     std::uint8_t maxNeighborDistance) const {
0056   ProtoLayer protoLayer =
0057       _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
0058   if (!_protoLayer) {
0059     protoLayer.envelope[AxisDirection::AxisR] = m_cfg.defaultEnvelopeR;
0060     protoLayer.envelope[AxisDirection::AxisZ] = m_cfg.defaultEnvelopeZ;
0061   }
0062 
0063   // Remaining layer parameters - they include the envelopes
0064   double layerR = protoLayer.medium(AxisDirection::AxisR);
0065   double layerZ = protoLayer.medium(AxisDirection::AxisZ);
0066   double layerHalfZ = 0.5 * protoLayer.range(AxisDirection::AxisZ);
0067   double layerThickness = protoLayer.range(AxisDirection::AxisR);
0068 
0069   ACTS_VERBOSE("Creating a cylindrical Layer:");
0070   ACTS_VERBOSE(" - with layer R     = " << layerR);
0071   ACTS_VERBOSE(" - from R min/max   = "
0072                << protoLayer.min(AxisDirection::AxisR, false) << " / "
0073                << protoLayer.max(AxisDirection::AxisR, false));
0074   ACTS_VERBOSE(" - with R thickness = " << layerThickness);
0075   ACTS_VERBOSE("   - incl envelope  = "
0076                << protoLayer.envelope[AxisDirection::AxisR][0u] << " / "
0077                << protoLayer.envelope[AxisDirection::AxisR][1u]);
0078 
0079   ACTS_VERBOSE(" - with z min/max   = "
0080                << protoLayer.min(AxisDirection::AxisZ, false) << " (-"
0081                << protoLayer.envelope[AxisDirection::AxisZ][0u] << ") / "
0082                << protoLayer.max(AxisDirection::AxisZ, false) << " (+"
0083                << protoLayer.envelope[AxisDirection::AxisZ][1u] << ")");
0084 
0085   ACTS_VERBOSE(" - z center         = " << layerZ);
0086   ACTS_VERBOSE(" - halflength z     = " << layerHalfZ);
0087 
0088   // create the layer transforms if not given
0089   // we need to transform in case layerZ != 0, so that the layer will be
0090   // correctly defined using the halflength
0091   Transform3 fullTransform = transform;
0092   if (fullTransform.isApprox(Transform3::Identity())) {
0093     fullTransform = Translation3(0, 0, layerZ) * fullTransform;
0094     ACTS_VERBOSE(" - layer z shift  = " << -layerZ);
0095   }
0096 
0097   ACTS_VERBOSE(" - with phi min/max = "
0098                << protoLayer.min(AxisDirection::AxisPhi, false) << " / "
0099                << protoLayer.max(AxisDirection::AxisPhi, false));
0100   ACTS_VERBOSE(" - # of modules     = " << surfaces.size() << " ordered in ( "
0101                                         << binsPhi << " x " << binsZ << ")");
0102   std::unique_ptr<SurfaceArray> sArray;
0103   if (!surfaces.empty()) {
0104     sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnCylinder(
0105         gctx, std::move(surfaces), binsPhi, binsZ, protoLayer, fullTransform,
0106         maxNeighborDistance);
0107   }
0108 
0109   // create the layer and push it back
0110   std::shared_ptr<const CylinderBounds> cBounds(
0111       new CylinderBounds(layerR, layerHalfZ));
0112 
0113   // create the layer
0114   MutableLayerPtr cLayer =
0115       CylinderLayer::create(fullTransform, cBounds, std::move(sArray),
0116                             layerThickness, std::move(ad), active);
0117 
0118   if (!cLayer) {
0119     ACTS_ERROR("Creation of cylinder layer did not succeed!");
0120   }
0121   associateSurfacesToLayer(*cLayer);
0122 
0123   // now return
0124   return cLayer;
0125 }
0126 
0127 MutableLayerPtr LayerCreator::cylinderLayer(
0128     const GeometryContext& gctx,
0129     std::vector<std::shared_ptr<const Surface>> surfaces, BinningType bTypePhi,
0130     BinningType bTypeZ, std::optional<ProtoLayer> _protoLayer,
0131     const Transform3& transform, std::unique_ptr<ApproachDescriptor> ad,
0132     std::uint8_t maxNeighborDistance) const {
0133   ProtoLayer protoLayer =
0134       _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
0135   if (!_protoLayer) {
0136     protoLayer.envelope[AxisDirection::AxisR] = m_cfg.defaultEnvelopeR;
0137     protoLayer.envelope[AxisDirection::AxisZ] = m_cfg.defaultEnvelopeZ;
0138   }
0139 
0140   // remaining layer parameters
0141   double layerR = protoLayer.medium(AxisDirection::AxisR);
0142   double layerZ = protoLayer.medium(AxisDirection::AxisZ);
0143   double layerHalfZ = 0.5 * protoLayer.range(AxisDirection::AxisZ);
0144   double layerThickness = protoLayer.range(AxisDirection::AxisR);
0145 
0146   // adjust the layer radius
0147   ACTS_VERBOSE("Creating a cylindrical Layer:");
0148   ACTS_VERBOSE(" - with layer R     = " << layerR);
0149   ACTS_VERBOSE(" - from R min/max   = "
0150                << protoLayer.min(AxisDirection::AxisR, false) << " / "
0151                << protoLayer.max(AxisDirection::AxisR, false));
0152   ACTS_VERBOSE(" - with R thickness = " << layerThickness);
0153   ACTS_VERBOSE("   - incl envelope  = "
0154                << protoLayer.envelope[AxisDirection::AxisR][0u] << " / "
0155                << protoLayer.envelope[AxisDirection::AxisR][1u]);
0156   ACTS_VERBOSE(" - with z min/max   = "
0157                << protoLayer.min(AxisDirection::AxisZ, false) << " (-"
0158                << protoLayer.envelope[AxisDirection::AxisZ][0u] << ") / "
0159                << protoLayer.max(AxisDirection::AxisZ, false) << " (+"
0160                << protoLayer.envelope[AxisDirection::AxisZ][1u] << ")");
0161   ACTS_VERBOSE(" - z center         = " << layerZ);
0162   ACTS_VERBOSE(" - halflength z     = " << layerHalfZ);
0163 
0164   // create the layer transforms if not given
0165   // we need to transform in case layerZ != 0, so that the layer will be
0166   // correctly defined using the halflength
0167   // create the layer transforms if not given
0168   Transform3 fullTransform = transform;
0169   if (fullTransform.isApprox(Transform3::Identity()) && bTypeZ == equidistant) {
0170     fullTransform = Translation3(0, 0, layerZ) * fullTransform;
0171     ACTS_VERBOSE(" - layer z shift    = " << -layerZ);
0172   }
0173 
0174   ACTS_VERBOSE(" - with phi min/max = "
0175                << protoLayer.min(AxisDirection::AxisPhi, false) << " / "
0176                << protoLayer.max(AxisDirection::AxisPhi, false));
0177   ACTS_VERBOSE(" - # of modules     = " << surfaces.size() << "");
0178 
0179   // create the surface array
0180   std::unique_ptr<SurfaceArray> sArray;
0181   if (!surfaces.empty()) {
0182     sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnCylinder(
0183         gctx, std::move(surfaces), bTypePhi, bTypeZ, protoLayer, fullTransform,
0184         maxNeighborDistance);
0185   }
0186 
0187   // create the layer and push it back
0188   std::shared_ptr<const CylinderBounds> cBounds(
0189       new CylinderBounds(layerR, layerHalfZ));
0190 
0191   // create the layer
0192   MutableLayerPtr cLayer =
0193       CylinderLayer::create(fullTransform, cBounds, std::move(sArray),
0194                             layerThickness, std::move(ad), active);
0195 
0196   if (!cLayer) {
0197     ACTS_ERROR("Creation of cylinder layer did not succeed!");
0198   }
0199   associateSurfacesToLayer(*cLayer);
0200 
0201   // now return
0202   return cLayer;
0203 }
0204 
0205 MutableLayerPtr LayerCreator::discLayer(
0206     const GeometryContext& gctx,
0207     std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t binsR,
0208     std::size_t binsPhi, std::optional<ProtoLayer> _protoLayer,
0209     const Transform3& transform, std::unique_ptr<ApproachDescriptor> ad,
0210     std::uint8_t maxNeighborDistance) const {
0211   ProtoLayer protoLayer =
0212       _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
0213   if (!_protoLayer) {
0214     protoLayer.envelope[AxisDirection::AxisR] = m_cfg.defaultEnvelopeR;
0215     protoLayer.envelope[AxisDirection::AxisZ] = m_cfg.defaultEnvelopeZ;
0216   }
0217 
0218   double layerZ = protoLayer.medium(AxisDirection::AxisZ);
0219   double layerThickness = protoLayer.range(AxisDirection::AxisZ);
0220 
0221   // adjust the layer radius
0222   ACTS_VERBOSE("Creating a disk Layer:");
0223   ACTS_VERBOSE(" - at Z position    = " << layerZ);
0224   ACTS_VERBOSE(" - from Z min/max   = "
0225                << protoLayer.min(AxisDirection::AxisZ, false) << " / "
0226                << protoLayer.max(AxisDirection::AxisZ, false));
0227   ACTS_VERBOSE(" - with Z thickness = " << layerThickness);
0228   ACTS_VERBOSE("   - incl envelope  = "
0229                << protoLayer.envelope[AxisDirection::AxisZ][0u] << " / "
0230                << protoLayer.envelope[AxisDirection::AxisZ][1u]);
0231   ACTS_VERBOSE(" - with R min/max   = "
0232                << protoLayer.min(AxisDirection::AxisR, false) << " (-"
0233                << protoLayer.envelope[AxisDirection::AxisR][0u] << ") / "
0234                << protoLayer.max(AxisDirection::AxisR, false) << " (+"
0235                << protoLayer.envelope[AxisDirection::AxisR][1u] << ")");
0236   ACTS_VERBOSE(" - with phi min/max = "
0237                << protoLayer.min(AxisDirection::AxisPhi, false) << " / "
0238                << protoLayer.max(AxisDirection::AxisPhi, false));
0239   ACTS_VERBOSE(" - # of modules    = " << surfaces.size() << " ordered in ( "
0240                                        << binsR << " x " << binsPhi << ")");
0241 
0242   // create the layer transforms if not given
0243   Transform3 fullTransform = transform;
0244   if (fullTransform.isApprox(Transform3::Identity())) {
0245     fullTransform = Translation3(0, 0, layerZ) * fullTransform;
0246   }
0247   // create the surface array
0248   std::unique_ptr<SurfaceArray> sArray;
0249   if (!surfaces.empty()) {
0250     sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnDisc(
0251         gctx, std::move(surfaces), binsR, binsPhi, protoLayer, fullTransform,
0252         maxNeighborDistance);
0253   }
0254 
0255   // create the share disc bounds
0256   auto dBounds = std::make_shared<const RadialBounds>(
0257       protoLayer.min(AxisDirection::AxisR),
0258       protoLayer.max(AxisDirection::AxisR));
0259 
0260   // create the layers
0261   // we use the same transform here as for the layer itself
0262   // for disk this is fine since we don't bin in Z, so does not matter
0263   MutableLayerPtr dLayer =
0264       DiscLayer::create(fullTransform, dBounds, std::move(sArray),
0265                         layerThickness, std::move(ad), active);
0266 
0267   if (!dLayer) {
0268     ACTS_ERROR("Creation of disc layer did not succeed!");
0269   }
0270   associateSurfacesToLayer(*dLayer);
0271   // return the layer
0272   return dLayer;
0273 }
0274 
0275 MutableLayerPtr LayerCreator::discLayer(
0276     const GeometryContext& gctx,
0277     std::vector<std::shared_ptr<const Surface>> surfaces, BinningType bTypeR,
0278     BinningType bTypePhi, std::optional<ProtoLayer> _protoLayer,
0279     const Transform3& transform, std::unique_ptr<ApproachDescriptor> ad,
0280     std::uint8_t maxNeighborDistance) const {
0281   ProtoLayer protoLayer =
0282       _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
0283   if (!_protoLayer) {
0284     protoLayer.envelope[AxisDirection::AxisR] = m_cfg.defaultEnvelopeR;
0285     protoLayer.envelope[AxisDirection::AxisZ] = m_cfg.defaultEnvelopeZ;
0286   }
0287 
0288   const double layerZ = protoLayer.medium(AxisDirection::AxisZ);
0289   const double layerThickness = protoLayer.range(AxisDirection::AxisZ);
0290 
0291   // adjust the layer radius
0292   ACTS_VERBOSE("Creating a disk Layer:");
0293   ACTS_VERBOSE(" - at Z position    = " << layerZ);
0294   ACTS_VERBOSE(" - from Z min/max   = "
0295                << protoLayer.min(AxisDirection::AxisZ, false) << " / "
0296                << protoLayer.max(AxisDirection::AxisZ, false));
0297   ACTS_VERBOSE(" - with Z thickness = " << layerThickness);
0298   ACTS_VERBOSE("   - incl envelope  = "
0299                << protoLayer.envelope[AxisDirection::AxisZ][0u] << " / "
0300                << protoLayer.envelope[AxisDirection::AxisZ][1u]);
0301   ACTS_VERBOSE(" - with R min/max   = "
0302                << protoLayer.min(AxisDirection::AxisR, false) << " (-"
0303                << protoLayer.envelope[AxisDirection::AxisR][0u] << ") / "
0304                << protoLayer.max(AxisDirection::AxisR, false) << " (+"
0305                << protoLayer.envelope[AxisDirection::AxisR][1u] << ")");
0306   ACTS_VERBOSE(" - with phi min/max = "
0307                << protoLayer.min(AxisDirection::AxisPhi, false) << " / "
0308                << protoLayer.max(AxisDirection::AxisPhi, false));
0309   ACTS_VERBOSE(" - # of modules     = " << surfaces.size());
0310 
0311   // create the layer transforms if not given
0312   Transform3 fullTransform = transform;
0313   if (fullTransform.isApprox(Transform3::Identity())) {
0314     fullTransform = Translation3(0, 0, layerZ) * fullTransform;
0315   }
0316 
0317   // create the surface array
0318   std::unique_ptr<SurfaceArray> sArray;
0319   if (!surfaces.empty()) {
0320     sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnDisc(
0321         gctx, std::move(surfaces), bTypeR, bTypePhi, protoLayer, fullTransform,
0322         maxNeighborDistance);
0323   }
0324 
0325   // create the shared disc bounds
0326   auto dBounds = std::make_shared<const RadialBounds>(
0327       protoLayer.min(AxisDirection::AxisR),
0328       protoLayer.max(AxisDirection::AxisR));
0329 
0330   // create the layers
0331   MutableLayerPtr dLayer =
0332       DiscLayer::create(fullTransform, dBounds, std::move(sArray),
0333                         layerThickness, std::move(ad), active);
0334   if (!dLayer) {
0335     ACTS_ERROR("Creation of disc layer did not succeed!");
0336   }
0337   associateSurfacesToLayer(*dLayer);
0338   // return the layer
0339   return dLayer;
0340 }
0341 
0342 MutableLayerPtr LayerCreator::planeLayer(
0343     const GeometryContext& gctx,
0344     std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t bins1,
0345     std::size_t bins2, AxisDirection aDir,
0346     std::optional<ProtoLayer> _protoLayer, const Transform3& transform,
0347     std::unique_ptr<ApproachDescriptor> ad,
0348     std::uint8_t maxNeighborDistance) const {
0349   ProtoLayer protoLayer =
0350       _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
0351   if (!_protoLayer) {
0352     protoLayer.envelope[AxisDirection::AxisR] = m_cfg.defaultEnvelopeR;
0353     protoLayer.envelope[AxisDirection::AxisZ] = m_cfg.defaultEnvelopeZ;
0354   }
0355 
0356   // remaining layer parameters
0357   double layerHalf1 = 0, layerHalf2 = 0, layerThickness = 0;
0358   switch (aDir) {
0359     case AxisDirection::AxisX: {
0360       layerHalf1 = 0.5 * protoLayer.range(AxisDirection::AxisY);
0361       layerHalf2 = 0.5 * protoLayer.range(AxisDirection::AxisZ);
0362       layerThickness = protoLayer.range(AxisDirection::AxisX);
0363       break;
0364     }
0365     case AxisDirection::AxisY: {
0366       layerHalf1 = 0.5 * protoLayer.range(AxisDirection::AxisX);
0367       layerHalf2 = 0.5 * protoLayer.range(AxisDirection::AxisZ);
0368       layerThickness = protoLayer.range(AxisDirection::AxisY);
0369       break;
0370     }
0371     case AxisDirection::AxisZ: {
0372       layerHalf1 = 0.5 * protoLayer.range(AxisDirection::AxisX);
0373       layerHalf2 = 0.5 * protoLayer.range(AxisDirection::AxisY);
0374       layerThickness = protoLayer.range(AxisDirection::AxisZ);
0375       break;
0376     }
0377     default:
0378       throw std::invalid_argument("Invalid binning value");
0379   }
0380 
0381   const double centerX = protoLayer.medium(AxisDirection::AxisX);
0382   const double centerY = protoLayer.medium(AxisDirection::AxisY);
0383   const double centerZ = protoLayer.medium(AxisDirection::AxisZ);
0384 
0385   ACTS_VERBOSE("Creating a plane Layer:");
0386   ACTS_VERBOSE(" - with layer center     = "
0387                << "(" << centerX << ", " << centerY << ", " << centerZ << ")");
0388   ACTS_VERBOSE(" - from X min/max   = "
0389                << protoLayer.min(AxisDirection::AxisX) << " / "
0390                << protoLayer.max(AxisDirection::AxisX));
0391   ACTS_VERBOSE(" - from Y min/max   = "
0392                << protoLayer.min(AxisDirection::AxisY) << " / "
0393                << protoLayer.max(AxisDirection::AxisY));
0394   ACTS_VERBOSE(" - with Z thickness = " << layerThickness);
0395   ACTS_VERBOSE("   - incl envelope  = " << protoLayer.envelope[aDir][0u]
0396                                         << " / "
0397                                         << protoLayer.envelope[aDir][1u]);
0398 
0399   // create the layer transforms if not given
0400   // we need to transform in case centerX/centerY/centerZ != 0, so that the
0401   // layer will be correctly defined
0402   Transform3 fullTransform = transform;
0403   if (fullTransform.isApprox(Transform3::Identity())) {
0404     fullTransform = Translation3(centerX, centerY, centerZ) * fullTransform;
0405     ACTS_VERBOSE(" - layer shift  = " << "(" << centerX << ", " << centerY
0406                                       << ", " << centerZ << ")");
0407   }
0408 
0409   std::unique_ptr<SurfaceArray> sArray;
0410   if (!surfaces.empty()) {
0411     sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnPlane(
0412         gctx, std::move(surfaces), bins1, bins2, aDir, protoLayer,
0413         fullTransform, maxNeighborDistance);
0414   }
0415 
0416   // create the layer and push it back
0417   auto pBounds = std::make_shared<RectangleBounds>(layerHalf1, layerHalf2);
0418 
0419   // create the layer
0420   MutableLayerPtr pLayer =
0421       PlaneLayer::create(fullTransform, pBounds, std::move(sArray),
0422                          layerThickness, std::move(ad), active);
0423 
0424   if (!pLayer) {
0425     ACTS_ERROR("Creation of plane layer did not succeed!");
0426   }
0427   associateSurfacesToLayer(*pLayer);
0428 
0429   // now return
0430   return pLayer;
0431 }
0432 
0433 void LayerCreator::associateSurfacesToLayer(Layer& layer) const {
0434   if (layer.surfaceArray() != nullptr) {
0435     auto surfaces = layer.surfaceArray()->surfaces();
0436 
0437     for (auto& surface : surfaces) {
0438       auto mutableSurface = const_cast<Surface*>(surface);
0439       mutableSurface->associateLayer(layer);
0440     }
0441   }
0442 }
0443 
0444 }  // namespace Acts