File indexing completed on 2025-01-18 09:11:23
0001
0002
0003
0004
0005
0006
0007
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
0024 #include <algorithm>
0025 #include <array>
0026 #include <iterator>
0027 #include <ostream>
0028 #include <set>
0029 #include <utility>
0030
0031 namespace Acts {
0032 class PlanarBounds;
0033 }
0034
0035 using Acts::VectorHelpers::perp;
0036 using Acts::VectorHelpers::phi;
0037
0038 Acts::LayerCreator::LayerCreator(const Acts::LayerCreator::Config& lcConfig,
0039 std::unique_ptr<const Logger> logger)
0040 : m_cfg(lcConfig), m_logger(std::move(logger)) {}
0041
0042 void Acts::LayerCreator::setConfiguration(
0043 const Acts::LayerCreator::Config& lcConfig) {
0044
0045
0046 m_cfg = lcConfig;
0047 }
0048
0049 void Acts::LayerCreator::setLogger(std::unique_ptr<const Logger> newLogger) {
0050 m_logger = std::move(newLogger);
0051 }
0052
0053 Acts::MutableLayerPtr Acts::LayerCreator::cylinderLayer(
0054 const GeometryContext& gctx,
0055 std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t binsPhi,
0056 std::size_t binsZ, std::optional<ProtoLayer> _protoLayer,
0057 const Transform3& transform, std::unique_ptr<ApproachDescriptor> ad) const {
0058 ProtoLayer protoLayer =
0059 _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
0060
0061
0062 double layerR = protoLayer.medium(AxisDirection::AxisR);
0063 double layerZ = protoLayer.medium(AxisDirection::AxisZ);
0064 double layerHalfZ = 0.5 * protoLayer.range(AxisDirection::AxisZ);
0065 double layerThickness = protoLayer.range(AxisDirection::AxisR);
0066
0067 ACTS_VERBOSE("Creating a cylindrical Layer:");
0068 ACTS_VERBOSE(" - with layer R = " << layerR);
0069 ACTS_VERBOSE(" - from R min/max = "
0070 << protoLayer.min(AxisDirection::AxisR, false) << " / "
0071 << protoLayer.max(AxisDirection::AxisR, false));
0072 ACTS_VERBOSE(" - with R thickness = " << layerThickness);
0073 ACTS_VERBOSE(" - incl envelope = "
0074 << protoLayer.envelope[AxisDirection::AxisR][0u] << " / "
0075 << protoLayer.envelope[AxisDirection::AxisR][1u]);
0076
0077 ACTS_VERBOSE(" - with z min/max = "
0078 << protoLayer.min(AxisDirection::AxisZ, false) << " (-"
0079 << protoLayer.envelope[AxisDirection::AxisZ][0u] << ") / "
0080 << protoLayer.max(AxisDirection::AxisZ, false) << " (+"
0081 << protoLayer.envelope[AxisDirection::AxisZ][1u] << ")");
0082
0083 ACTS_VERBOSE(" - z center = " << layerZ);
0084 ACTS_VERBOSE(" - halflength z = " << layerHalfZ);
0085
0086
0087
0088
0089 Translation3 addTranslation(0., 0., 0.);
0090 if (transform.isApprox(Transform3::Identity())) {
0091 addTranslation = Translation3(0., 0., layerZ);
0092 ACTS_VERBOSE(" - layer z shift = " << -layerZ);
0093 }
0094
0095 ACTS_VERBOSE(" - with phi min/max = "
0096 << protoLayer.min(AxisDirection::AxisPhi, false) << " / "
0097 << protoLayer.max(AxisDirection::AxisPhi, false));
0098 ACTS_VERBOSE(" - # of modules = " << surfaces.size() << " ordered in ( "
0099 << binsPhi << " x " << binsZ << ")");
0100 std::unique_ptr<SurfaceArray> sArray;
0101 if (!surfaces.empty()) {
0102 sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnCylinder(
0103 gctx, std::move(surfaces), binsPhi, binsZ, protoLayer);
0104
0105 checkBinning(gctx, *sArray);
0106 }
0107
0108
0109 std::shared_ptr<const CylinderBounds> cBounds(
0110 new CylinderBounds(layerR, layerHalfZ));
0111
0112
0113 MutableLayerPtr cLayer = CylinderLayer::create(
0114 addTranslation * transform, cBounds, std::move(sArray), layerThickness,
0115 std::move(ad), active);
0116
0117 if (!cLayer) {
0118 ACTS_ERROR("Creation of cylinder layer did not succeed!");
0119 }
0120 associateSurfacesToLayer(*cLayer);
0121
0122
0123 return cLayer;
0124 }
0125
0126 Acts::MutableLayerPtr Acts::LayerCreator::cylinderLayer(
0127 const GeometryContext& gctx,
0128 std::vector<std::shared_ptr<const Surface>> surfaces, BinningType bTypePhi,
0129 BinningType bTypeZ, std::optional<ProtoLayer> _protoLayer,
0130 const Transform3& transform, std::unique_ptr<ApproachDescriptor> ad) const {
0131 ProtoLayer protoLayer =
0132 _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
0133
0134
0135 double layerR = protoLayer.medium(AxisDirection::AxisR);
0136 double layerZ = protoLayer.medium(AxisDirection::AxisZ);
0137 double layerHalfZ = 0.5 * protoLayer.range(AxisDirection::AxisZ);
0138 double layerThickness = protoLayer.range(AxisDirection::AxisR);
0139
0140
0141 ACTS_VERBOSE("Creating a cylindrical Layer:");
0142 ACTS_VERBOSE(" - with layer R = " << layerR);
0143 ACTS_VERBOSE(" - from R min/max = "
0144 << protoLayer.min(AxisDirection::AxisR, false) << " / "
0145 << protoLayer.max(AxisDirection::AxisR, false));
0146 ACTS_VERBOSE(" - with R thickness = " << layerThickness);
0147 ACTS_VERBOSE(" - incl envelope = "
0148 << protoLayer.envelope[AxisDirection::AxisR][0u] << " / "
0149 << protoLayer.envelope[AxisDirection::AxisR][1u]);
0150 ACTS_VERBOSE(" - with z min/max = "
0151 << protoLayer.min(AxisDirection::AxisZ, false) << " (-"
0152 << protoLayer.envelope[AxisDirection::AxisZ][0u] << ") / "
0153 << protoLayer.max(AxisDirection::AxisZ, false) << " (+"
0154 << protoLayer.envelope[AxisDirection::AxisZ][1u] << ")");
0155 ACTS_VERBOSE(" - z center = " << layerZ);
0156 ACTS_VERBOSE(" - halflength z = " << layerHalfZ);
0157
0158
0159
0160
0161
0162 Translation3 addTranslation(0., 0., 0.);
0163 if (transform.isApprox(Transform3::Identity()) && bTypeZ == equidistant) {
0164 addTranslation = Translation3(0., 0., layerZ);
0165 ACTS_VERBOSE(" - layer z shift = " << -layerZ);
0166 }
0167
0168 ACTS_VERBOSE(" - with phi min/max = "
0169 << protoLayer.min(AxisDirection::AxisPhi, false) << " / "
0170 << protoLayer.max(AxisDirection::AxisPhi, false));
0171 ACTS_VERBOSE(" - # of modules = " << surfaces.size() << "");
0172
0173
0174 std::unique_ptr<SurfaceArray> sArray;
0175 if (!surfaces.empty()) {
0176 sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnCylinder(
0177 gctx, std::move(surfaces), bTypePhi, bTypeZ, protoLayer);
0178
0179 checkBinning(gctx, *sArray);
0180 }
0181
0182
0183 std::shared_ptr<const CylinderBounds> cBounds(
0184 new CylinderBounds(layerR, layerHalfZ));
0185
0186
0187 MutableLayerPtr cLayer = CylinderLayer::create(
0188 addTranslation * transform, cBounds, std::move(sArray), layerThickness,
0189 std::move(ad), active);
0190
0191 if (!cLayer) {
0192 ACTS_ERROR("Creation of cylinder layer did not succeed!");
0193 }
0194 associateSurfacesToLayer(*cLayer);
0195
0196
0197 return cLayer;
0198 }
0199
0200 Acts::MutableLayerPtr Acts::LayerCreator::discLayer(
0201 const GeometryContext& gctx,
0202 std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t binsR,
0203 std::size_t binsPhi, std::optional<ProtoLayer> _protoLayer,
0204 const Transform3& transform, std::unique_ptr<ApproachDescriptor> ad) const {
0205 ProtoLayer protoLayer =
0206 _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
0207
0208 double layerZ = protoLayer.medium(AxisDirection::AxisZ);
0209 double layerThickness = protoLayer.range(AxisDirection::AxisZ);
0210
0211
0212 ACTS_VERBOSE("Creating a disk Layer:");
0213 ACTS_VERBOSE(" - at Z position = " << layerZ);
0214 ACTS_VERBOSE(" - from Z min/max = "
0215 << protoLayer.min(AxisDirection::AxisZ, false) << " / "
0216 << protoLayer.max(AxisDirection::AxisZ, false));
0217 ACTS_VERBOSE(" - with Z thickness = " << layerThickness);
0218 ACTS_VERBOSE(" - incl envelope = "
0219 << protoLayer.envelope[AxisDirection::AxisZ][0u] << " / "
0220 << protoLayer.envelope[AxisDirection::AxisZ][1u]);
0221 ACTS_VERBOSE(" - with R min/max = "
0222 << protoLayer.min(AxisDirection::AxisR, false) << " (-"
0223 << protoLayer.envelope[AxisDirection::AxisR][0u] << ") / "
0224 << protoLayer.max(AxisDirection::AxisR, false) << " (+"
0225 << protoLayer.envelope[AxisDirection::AxisR][1u] << ")");
0226 ACTS_VERBOSE(" - with phi min/max = "
0227 << protoLayer.min(AxisDirection::AxisPhi, false) << " / "
0228 << protoLayer.max(AxisDirection::AxisPhi, false));
0229 ACTS_VERBOSE(" - # of modules = " << surfaces.size() << " ordered in ( "
0230 << binsR << " x " << binsPhi << ")");
0231
0232
0233 Translation3 addTranslation(0., 0., 0.);
0234 if (transform.isApprox(Transform3::Identity())) {
0235 addTranslation = Translation3(0., 0., layerZ);
0236 }
0237
0238 std::unique_ptr<SurfaceArray> sArray;
0239 if (!surfaces.empty()) {
0240 sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnDisc(
0241 gctx, std::move(surfaces), binsR, binsPhi, protoLayer, transform);
0242
0243 checkBinning(gctx, *sArray);
0244 }
0245
0246
0247 auto dBounds = std::make_shared<const RadialBounds>(
0248 protoLayer.min(AxisDirection::AxisR),
0249 protoLayer.max(AxisDirection::AxisR));
0250
0251
0252
0253
0254 MutableLayerPtr dLayer =
0255 DiscLayer::create(addTranslation * transform, dBounds, std::move(sArray),
0256 layerThickness, std::move(ad), active);
0257
0258 if (!dLayer) {
0259 ACTS_ERROR("Creation of disc layer did not succeed!");
0260 }
0261 associateSurfacesToLayer(*dLayer);
0262
0263 return dLayer;
0264 }
0265
0266 Acts::MutableLayerPtr Acts::LayerCreator::discLayer(
0267 const GeometryContext& gctx,
0268 std::vector<std::shared_ptr<const Surface>> surfaces, BinningType bTypeR,
0269 BinningType bTypePhi, std::optional<ProtoLayer> _protoLayer,
0270 const Transform3& transform, std::unique_ptr<ApproachDescriptor> ad) const {
0271 ProtoLayer protoLayer =
0272 _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
0273
0274 double layerZ = protoLayer.medium(AxisDirection::AxisZ);
0275 double layerThickness = protoLayer.range(AxisDirection::AxisZ);
0276
0277
0278 ACTS_VERBOSE("Creating a disk Layer:");
0279 ACTS_VERBOSE(" - at Z position = " << layerZ);
0280 ACTS_VERBOSE(" - from Z min/max = "
0281 << protoLayer.min(AxisDirection::AxisZ, false) << " / "
0282 << protoLayer.max(AxisDirection::AxisZ, false));
0283 ACTS_VERBOSE(" - with Z thickness = " << layerThickness);
0284 ACTS_VERBOSE(" - incl envelope = "
0285 << protoLayer.envelope[AxisDirection::AxisZ][0u] << " / "
0286 << protoLayer.envelope[AxisDirection::AxisZ][1u]);
0287 ACTS_VERBOSE(" - with R min/max = "
0288 << protoLayer.min(AxisDirection::AxisR, false) << " (-"
0289 << protoLayer.envelope[AxisDirection::AxisR][0u] << ") / "
0290 << protoLayer.max(AxisDirection::AxisR, false) << " (+"
0291 << protoLayer.envelope[AxisDirection::AxisR][1u] << ")");
0292 ACTS_VERBOSE(" - with phi min/max = "
0293 << protoLayer.min(AxisDirection::AxisPhi, false) << " / "
0294 << protoLayer.max(AxisDirection::AxisPhi, false));
0295 ACTS_VERBOSE(" - # of modules = " << surfaces.size());
0296
0297
0298 Translation3 addTranslation(0., 0., 0.);
0299 if (transform.isApprox(Transform3::Identity())) {
0300 addTranslation = Translation3(0., 0., layerZ);
0301 }
0302
0303
0304 std::unique_ptr<SurfaceArray> sArray;
0305 if (!surfaces.empty()) {
0306 sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnDisc(
0307 gctx, std::move(surfaces), bTypeR, bTypePhi, protoLayer, transform);
0308
0309 checkBinning(gctx, *sArray);
0310 }
0311
0312
0313 auto dBounds = std::make_shared<const RadialBounds>(
0314 protoLayer.min(AxisDirection::AxisR),
0315 protoLayer.max(AxisDirection::AxisR));
0316
0317
0318 MutableLayerPtr dLayer =
0319 DiscLayer::create(addTranslation * transform, dBounds, std::move(sArray),
0320 layerThickness, std::move(ad), active);
0321 if (!dLayer) {
0322 ACTS_ERROR("Creation of disc layer did not succeed!");
0323 }
0324 associateSurfacesToLayer(*dLayer);
0325
0326 return dLayer;
0327 }
0328
0329 Acts::MutableLayerPtr Acts::LayerCreator::planeLayer(
0330 const GeometryContext& gctx,
0331 std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t bins1,
0332 std::size_t bins2, AxisDirection aDir,
0333 std::optional<ProtoLayer> _protoLayer, const Transform3& transform,
0334 std::unique_ptr<ApproachDescriptor> ad) const {
0335 ProtoLayer protoLayer =
0336 _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
0337
0338
0339 double layerHalf1 = 0, layerHalf2 = 0, layerThickness = 0;
0340 switch (aDir) {
0341 case AxisDirection::AxisX: {
0342 layerHalf1 = 0.5 * (protoLayer.max(AxisDirection::AxisY) -
0343 protoLayer.min(AxisDirection::AxisY));
0344 layerHalf2 = 0.5 * (protoLayer.max(AxisDirection::AxisZ) -
0345 protoLayer.min(AxisDirection::AxisZ));
0346 layerThickness = (protoLayer.max(AxisDirection::AxisX) -
0347 protoLayer.min(AxisDirection::AxisX));
0348 break;
0349 }
0350 case AxisDirection::AxisY: {
0351 layerHalf1 = 0.5 * (protoLayer.max(AxisDirection::AxisX) -
0352 protoLayer.min(AxisDirection::AxisX));
0353 layerHalf2 = 0.5 * (protoLayer.max(AxisDirection::AxisZ) -
0354 protoLayer.min(AxisDirection::AxisZ));
0355 layerThickness = (protoLayer.max(AxisDirection::AxisY) -
0356 protoLayer.min(AxisDirection::AxisY));
0357 break;
0358 }
0359 case AxisDirection::AxisZ: {
0360 layerHalf1 = 0.5 * (protoLayer.max(AxisDirection::AxisX) -
0361 protoLayer.min(AxisDirection::AxisX));
0362 layerHalf2 = 0.5 * (protoLayer.max(AxisDirection::AxisY) -
0363 protoLayer.min(AxisDirection::AxisY));
0364 layerThickness = (protoLayer.max(AxisDirection::AxisZ) -
0365 protoLayer.min(AxisDirection::AxisZ));
0366 break;
0367 }
0368 default:
0369 throw std::invalid_argument("Invalid binning value");
0370 }
0371
0372 double centerX = 0.5 * (protoLayer.max(AxisDirection::AxisX) +
0373 protoLayer.min(AxisDirection::AxisX));
0374 double centerY = 0.5 * (protoLayer.max(AxisDirection::AxisY) +
0375 protoLayer.min(AxisDirection::AxisY));
0376 double centerZ = 0.5 * (protoLayer.max(AxisDirection::AxisZ) +
0377 protoLayer.min(AxisDirection::AxisZ));
0378
0379 ACTS_VERBOSE("Creating a plane Layer:");
0380 ACTS_VERBOSE(" - with layer center = "
0381 << "(" << centerX << ", " << centerY << ", " << centerZ << ")");
0382 ACTS_VERBOSE(" - from X min/max = "
0383 << protoLayer.min(AxisDirection::AxisX) << " / "
0384 << protoLayer.max(AxisDirection::AxisX));
0385 ACTS_VERBOSE(" - from Y min/max = "
0386 << protoLayer.min(AxisDirection::AxisY) << " / "
0387 << protoLayer.max(AxisDirection::AxisY));
0388 ACTS_VERBOSE(" - with Z thickness = " << layerThickness);
0389 ACTS_VERBOSE(" - incl envelope = " << protoLayer.envelope[aDir][0u]
0390 << " / "
0391 << protoLayer.envelope[aDir][1u]);
0392
0393
0394
0395
0396 Translation3 addTranslation(0., 0., 0.);
0397 if (transform.isApprox(Transform3::Identity())) {
0398 addTranslation = Translation3(centerX, centerY, centerZ);
0399 ACTS_VERBOSE(" - layer shift = " << "(" << centerX << ", " << centerY
0400 << ", " << centerZ << ")");
0401 }
0402
0403 std::unique_ptr<SurfaceArray> sArray;
0404 if (!surfaces.empty()) {
0405 sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnPlane(
0406 gctx, std::move(surfaces), bins1, bins2, aDir, protoLayer, transform);
0407
0408 checkBinning(gctx, *sArray);
0409 }
0410
0411
0412 auto pBounds = std::make_shared<RectangleBounds>(layerHalf1, layerHalf2);
0413
0414
0415 MutableLayerPtr pLayer =
0416 PlaneLayer::create(addTranslation * transform, pBounds, std::move(sArray),
0417 layerThickness, std::move(ad), active);
0418
0419 if (!pLayer) {
0420 ACTS_ERROR("Creation of plane layer did not succeed!");
0421 }
0422 associateSurfacesToLayer(*pLayer);
0423
0424
0425 return pLayer;
0426 }
0427
0428 void Acts::LayerCreator::associateSurfacesToLayer(Layer& layer) const {
0429 if (layer.surfaceArray() != nullptr) {
0430 auto surfaces = layer.surfaceArray()->surfaces();
0431
0432 for (auto& surface : surfaces) {
0433 auto mutableSurface = const_cast<Surface*>(surface);
0434 mutableSurface->associateLayer(layer);
0435 }
0436 }
0437 }
0438
0439 bool Acts::LayerCreator::checkBinning(const GeometryContext& gctx,
0440 const SurfaceArray& sArray) const {
0441
0442
0443
0444
0445 ACTS_VERBOSE("Performing consistency check");
0446
0447 std::vector<const Surface*> surfaces = sArray.surfaces();
0448 std::set<const Surface*> sensitiveSurfaces(surfaces.begin(), surfaces.end());
0449 std::set<const Surface*> accessibleSurfaces;
0450 std::size_t nEmptyBins = 0;
0451 std::size_t nBinsChecked = 0;
0452
0453
0454 std::size_t size = sArray.size();
0455 for (std::size_t b = 0; b < size; ++b) {
0456 std::vector<const Surface*> binContent = sArray.at(b);
0457
0458 if (!sArray.isValidBin(b)) {
0459 continue;
0460 }
0461 for (const auto& srf : binContent) {
0462 accessibleSurfaces.insert(srf);
0463 }
0464 if (binContent.empty()) {
0465 nEmptyBins++;
0466 }
0467 nBinsChecked++;
0468 }
0469
0470 std::vector<const Acts::Surface*> diff;
0471 std::set_difference(sensitiveSurfaces.begin(), sensitiveSurfaces.end(),
0472 accessibleSurfaces.begin(), accessibleSurfaces.end(),
0473 std::inserter(diff, diff.begin()));
0474
0475 ACTS_VERBOSE(" - Checked " << nBinsChecked << " valid bins");
0476
0477 if (nEmptyBins > 0) {
0478 ACTS_ERROR(" -- Not all bins point to surface. " << nEmptyBins << " empty");
0479 } else {
0480 ACTS_VERBOSE(" -- All bins point to a surface");
0481 }
0482
0483 if (!diff.empty()) {
0484 ACTS_ERROR(
0485 " -- Not all sensitive surfaces are accessible through binning. "
0486 "sensitive: "
0487 << sensitiveSurfaces.size()
0488 << " accessible: " << accessibleSurfaces.size());
0489
0490
0491 ACTS_ERROR(" -- Inaccessible surfaces: ");
0492 for (const auto& srf : diff) {
0493
0494 Vector3 ctr = srf->referencePosition(gctx, AxisDirection::AxisR);
0495 ACTS_ERROR(" Surface(x=" << ctr.x() << ", y=" << ctr.y()
0496 << ", z=" << ctr.z() << ", r=" << perp(ctr)
0497 << ", phi=" << phi(ctr) << ")");
0498 }
0499
0500 } else {
0501 ACTS_VERBOSE(" -- All sensitive surfaces are accessible through binning.");
0502 }
0503
0504 return nEmptyBins == 0 && diff.empty();
0505 }