Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-22 07:52:09

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 
0024 #include <algorithm>
0025 #include <iterator>
0026 #include <ostream>
0027 #include <set>
0028 #include <utility>
0029 
0030 namespace Acts {
0031 
0032 using VectorHelpers::perp;
0033 using VectorHelpers::phi;
0034 
0035 LayerCreator::LayerCreator(const LayerCreator::Config& lcConfig,
0036                            std::unique_ptr<const Logger> logger)
0037     : m_cfg(lcConfig), m_logger(std::move(logger)) {}
0038 
0039 void LayerCreator::setConfiguration(const LayerCreator::Config& lcConfig) {
0040   // @todo check consistency
0041   // copy the configuration
0042   m_cfg = lcConfig;
0043 }
0044 
0045 void LayerCreator::setLogger(std::unique_ptr<const Logger> newLogger) {
0046   m_logger = std::move(newLogger);
0047 }
0048 
0049 MutableLayerPtr LayerCreator::cylinderLayer(
0050     const GeometryContext& gctx,
0051     std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t binsPhi,
0052     std::size_t binsZ, std::optional<ProtoLayer> _protoLayer,
0053     const Transform3& transform, std::unique_ptr<ApproachDescriptor> ad) const {
0054   ProtoLayer protoLayer =
0055       _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
0056   if (!_protoLayer) {
0057     protoLayer.envelope[AxisDirection::AxisR] = m_cfg.defaultEnvelopeR;
0058     protoLayer.envelope[AxisDirection::AxisZ] = m_cfg.defaultEnvelopeZ;
0059   }
0060 
0061   // Remaining layer parameters - they include the envelopes
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   // create the layer transforms if not given
0087   // we need to transform in case layerZ != 0, so that the layer will be
0088   // correctly defined using the halflength
0089   Transform3 fullTransform = transform;
0090   if (fullTransform.isApprox(Transform3::Identity())) {
0091     fullTransform = Translation3(0, 0, layerZ) * fullTransform;
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, fullTransform);
0104 
0105     checkBinning(gctx, *sArray);
0106   }
0107 
0108   // create the layer and push it back
0109   std::shared_ptr<const CylinderBounds> cBounds(
0110       new CylinderBounds(layerR, layerHalfZ));
0111 
0112   // create the layer
0113   MutableLayerPtr cLayer =
0114       CylinderLayer::create(fullTransform, cBounds, std::move(sArray),
0115                             layerThickness, std::move(ad), active);
0116 
0117   if (!cLayer) {
0118     ACTS_ERROR("Creation of cylinder layer did not succeed!");
0119   }
0120   associateSurfacesToLayer(*cLayer);
0121 
0122   // now return
0123   return cLayer;
0124 }
0125 
0126 MutableLayerPtr 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   if (!_protoLayer) {
0134     protoLayer.envelope[AxisDirection::AxisR] = m_cfg.defaultEnvelopeR;
0135     protoLayer.envelope[AxisDirection::AxisZ] = m_cfg.defaultEnvelopeZ;
0136   }
0137 
0138   // remaining layer parameters
0139   double layerR = protoLayer.medium(AxisDirection::AxisR);
0140   double layerZ = protoLayer.medium(AxisDirection::AxisZ);
0141   double layerHalfZ = 0.5 * protoLayer.range(AxisDirection::AxisZ);
0142   double layerThickness = protoLayer.range(AxisDirection::AxisR);
0143 
0144   // adjust the layer radius
0145   ACTS_VERBOSE("Creating a cylindrical Layer:");
0146   ACTS_VERBOSE(" - with layer R     = " << layerR);
0147   ACTS_VERBOSE(" - from R min/max   = "
0148                << protoLayer.min(AxisDirection::AxisR, false) << " / "
0149                << protoLayer.max(AxisDirection::AxisR, false));
0150   ACTS_VERBOSE(" - with R thickness = " << layerThickness);
0151   ACTS_VERBOSE("   - incl envelope  = "
0152                << protoLayer.envelope[AxisDirection::AxisR][0u] << " / "
0153                << protoLayer.envelope[AxisDirection::AxisR][1u]);
0154   ACTS_VERBOSE(" - with z min/max   = "
0155                << protoLayer.min(AxisDirection::AxisZ, false) << " (-"
0156                << protoLayer.envelope[AxisDirection::AxisZ][0u] << ") / "
0157                << protoLayer.max(AxisDirection::AxisZ, false) << " (+"
0158                << protoLayer.envelope[AxisDirection::AxisZ][1u] << ")");
0159   ACTS_VERBOSE(" - z center         = " << layerZ);
0160   ACTS_VERBOSE(" - halflength z     = " << layerHalfZ);
0161 
0162   // create the layer transforms if not given
0163   // we need to transform in case layerZ != 0, so that the layer will be
0164   // correctly defined using the halflength
0165   // create the layer transforms if not given
0166   Transform3 fullTransform = transform;
0167   if (fullTransform.isApprox(Transform3::Identity()) && bTypeZ == equidistant) {
0168     fullTransform = Translation3(0, 0, layerZ) * fullTransform;
0169     ACTS_VERBOSE(" - layer z shift    = " << -layerZ);
0170   }
0171 
0172   ACTS_VERBOSE(" - with phi min/max = "
0173                << protoLayer.min(AxisDirection::AxisPhi, false) << " / "
0174                << protoLayer.max(AxisDirection::AxisPhi, false));
0175   ACTS_VERBOSE(" - # of modules     = " << surfaces.size() << "");
0176 
0177   // create the surface array
0178   std::unique_ptr<SurfaceArray> sArray;
0179   if (!surfaces.empty()) {
0180     sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnCylinder(
0181         gctx, std::move(surfaces), bTypePhi, bTypeZ, protoLayer, fullTransform);
0182 
0183     checkBinning(gctx, *sArray);
0184   }
0185 
0186   // create the layer and push it back
0187   std::shared_ptr<const CylinderBounds> cBounds(
0188       new CylinderBounds(layerR, layerHalfZ));
0189 
0190   // create the layer
0191   MutableLayerPtr cLayer =
0192       CylinderLayer::create(fullTransform, cBounds, std::move(sArray),
0193                             layerThickness, std::move(ad), active);
0194 
0195   if (!cLayer) {
0196     ACTS_ERROR("Creation of cylinder layer did not succeed!");
0197   }
0198   associateSurfacesToLayer(*cLayer);
0199 
0200   // now return
0201   return cLayer;
0202 }
0203 
0204 MutableLayerPtr LayerCreator::discLayer(
0205     const GeometryContext& gctx,
0206     std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t binsR,
0207     std::size_t binsPhi, std::optional<ProtoLayer> _protoLayer,
0208     const Transform3& transform, std::unique_ptr<ApproachDescriptor> ad) const {
0209   ProtoLayer protoLayer =
0210       _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
0211   if (!_protoLayer) {
0212     protoLayer.envelope[AxisDirection::AxisR] = m_cfg.defaultEnvelopeR;
0213     protoLayer.envelope[AxisDirection::AxisZ] = m_cfg.defaultEnvelopeZ;
0214   }
0215 
0216   double layerZ = protoLayer.medium(AxisDirection::AxisZ);
0217   double layerThickness = protoLayer.range(AxisDirection::AxisZ);
0218 
0219   // adjust the layer radius
0220   ACTS_VERBOSE("Creating a disk Layer:");
0221   ACTS_VERBOSE(" - at Z position    = " << layerZ);
0222   ACTS_VERBOSE(" - from Z min/max   = "
0223                << protoLayer.min(AxisDirection::AxisZ, false) << " / "
0224                << protoLayer.max(AxisDirection::AxisZ, false));
0225   ACTS_VERBOSE(" - with Z thickness = " << layerThickness);
0226   ACTS_VERBOSE("   - incl envelope  = "
0227                << protoLayer.envelope[AxisDirection::AxisZ][0u] << " / "
0228                << protoLayer.envelope[AxisDirection::AxisZ][1u]);
0229   ACTS_VERBOSE(" - with R min/max   = "
0230                << protoLayer.min(AxisDirection::AxisR, false) << " (-"
0231                << protoLayer.envelope[AxisDirection::AxisR][0u] << ") / "
0232                << protoLayer.max(AxisDirection::AxisR, false) << " (+"
0233                << protoLayer.envelope[AxisDirection::AxisR][1u] << ")");
0234   ACTS_VERBOSE(" - with phi min/max = "
0235                << protoLayer.min(AxisDirection::AxisPhi, false) << " / "
0236                << protoLayer.max(AxisDirection::AxisPhi, false));
0237   ACTS_VERBOSE(" - # of modules    = " << surfaces.size() << " ordered in ( "
0238                                        << binsR << " x " << binsPhi << ")");
0239 
0240   // create the layer transforms if not given
0241   Transform3 fullTransform = transform;
0242   if (fullTransform.isApprox(Transform3::Identity())) {
0243     fullTransform = Translation3(0, 0, layerZ) * fullTransform;
0244   }
0245   // create the surface array
0246   std::unique_ptr<SurfaceArray> sArray;
0247   if (!surfaces.empty()) {
0248     sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnDisc(
0249         gctx, std::move(surfaces), binsR, binsPhi, protoLayer, fullTransform);
0250 
0251     checkBinning(gctx, *sArray);
0252   }
0253 
0254   // create the share disc bounds
0255   auto dBounds = std::make_shared<const RadialBounds>(
0256       protoLayer.min(AxisDirection::AxisR),
0257       protoLayer.max(AxisDirection::AxisR));
0258 
0259   // create the layers
0260   // we use the same transform here as for the layer itself
0261   // for disk this is fine since we don't bin in Z, so does not matter
0262   MutableLayerPtr dLayer =
0263       DiscLayer::create(fullTransform, dBounds, std::move(sArray),
0264                         layerThickness, std::move(ad), active);
0265 
0266   if (!dLayer) {
0267     ACTS_ERROR("Creation of disc layer did not succeed!");
0268   }
0269   associateSurfacesToLayer(*dLayer);
0270   // return the layer
0271   return dLayer;
0272 }
0273 
0274 MutableLayerPtr LayerCreator::discLayer(
0275     const GeometryContext& gctx,
0276     std::vector<std::shared_ptr<const Surface>> surfaces, BinningType bTypeR,
0277     BinningType bTypePhi, std::optional<ProtoLayer> _protoLayer,
0278     const Transform3& transform, std::unique_ptr<ApproachDescriptor> ad) const {
0279   ProtoLayer protoLayer =
0280       _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
0281   if (!_protoLayer) {
0282     protoLayer.envelope[AxisDirection::AxisR] = m_cfg.defaultEnvelopeR;
0283     protoLayer.envelope[AxisDirection::AxisZ] = m_cfg.defaultEnvelopeZ;
0284   }
0285 
0286   const double layerZ = protoLayer.medium(AxisDirection::AxisZ);
0287   const double layerThickness = protoLayer.range(AxisDirection::AxisZ);
0288 
0289   // adjust the layer radius
0290   ACTS_VERBOSE("Creating a disk Layer:");
0291   ACTS_VERBOSE(" - at Z position    = " << layerZ);
0292   ACTS_VERBOSE(" - from Z min/max   = "
0293                << protoLayer.min(AxisDirection::AxisZ, false) << " / "
0294                << protoLayer.max(AxisDirection::AxisZ, false));
0295   ACTS_VERBOSE(" - with Z thickness = " << layerThickness);
0296   ACTS_VERBOSE("   - incl envelope  = "
0297                << protoLayer.envelope[AxisDirection::AxisZ][0u] << " / "
0298                << protoLayer.envelope[AxisDirection::AxisZ][1u]);
0299   ACTS_VERBOSE(" - with R min/max   = "
0300                << protoLayer.min(AxisDirection::AxisR, false) << " (-"
0301                << protoLayer.envelope[AxisDirection::AxisR][0u] << ") / "
0302                << protoLayer.max(AxisDirection::AxisR, false) << " (+"
0303                << protoLayer.envelope[AxisDirection::AxisR][1u] << ")");
0304   ACTS_VERBOSE(" - with phi min/max = "
0305                << protoLayer.min(AxisDirection::AxisPhi, false) << " / "
0306                << protoLayer.max(AxisDirection::AxisPhi, false));
0307   ACTS_VERBOSE(" - # of modules     = " << surfaces.size());
0308 
0309   // create the layer transforms if not given
0310   Transform3 fullTransform = transform;
0311   if (fullTransform.isApprox(Transform3::Identity())) {
0312     fullTransform = Translation3(0, 0, layerZ) * fullTransform;
0313   }
0314 
0315   // create the surface array
0316   std::unique_ptr<SurfaceArray> sArray;
0317   if (!surfaces.empty()) {
0318     sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnDisc(
0319         gctx, std::move(surfaces), bTypeR, bTypePhi, protoLayer, fullTransform);
0320 
0321     checkBinning(gctx, *sArray);
0322   }
0323 
0324   // create the shared disc bounds
0325   auto dBounds = std::make_shared<const RadialBounds>(
0326       protoLayer.min(AxisDirection::AxisR),
0327       protoLayer.max(AxisDirection::AxisR));
0328 
0329   // create the layers
0330   MutableLayerPtr dLayer =
0331       DiscLayer::create(fullTransform, dBounds, std::move(sArray),
0332                         layerThickness, std::move(ad), active);
0333   if (!dLayer) {
0334     ACTS_ERROR("Creation of disc layer did not succeed!");
0335   }
0336   associateSurfacesToLayer(*dLayer);
0337   // return the layer
0338   return dLayer;
0339 }
0340 
0341 MutableLayerPtr LayerCreator::planeLayer(
0342     const GeometryContext& gctx,
0343     std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t bins1,
0344     std::size_t bins2, AxisDirection aDir,
0345     std::optional<ProtoLayer> _protoLayer, const Transform3& transform,
0346     std::unique_ptr<ApproachDescriptor> ad) const {
0347   ProtoLayer protoLayer =
0348       _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
0349   if (!_protoLayer) {
0350     protoLayer.envelope[AxisDirection::AxisR] = m_cfg.defaultEnvelopeR;
0351     protoLayer.envelope[AxisDirection::AxisZ] = m_cfg.defaultEnvelopeZ;
0352   }
0353 
0354   // remaining layer parameters
0355   double layerHalf1 = 0, layerHalf2 = 0, layerThickness = 0;
0356   switch (aDir) {
0357     case AxisDirection::AxisX: {
0358       layerHalf1 = 0.5 * protoLayer.range(AxisDirection::AxisY);
0359       layerHalf2 = 0.5 * protoLayer.range(AxisDirection::AxisZ);
0360       layerThickness = protoLayer.range(AxisDirection::AxisX);
0361       break;
0362     }
0363     case AxisDirection::AxisY: {
0364       layerHalf1 = 0.5 * protoLayer.range(AxisDirection::AxisX);
0365       layerHalf2 = 0.5 * protoLayer.range(AxisDirection::AxisZ);
0366       layerThickness = protoLayer.range(AxisDirection::AxisY);
0367       break;
0368     }
0369     case AxisDirection::AxisZ: {
0370       layerHalf1 = 0.5 * protoLayer.range(AxisDirection::AxisX);
0371       layerHalf2 = 0.5 * protoLayer.range(AxisDirection::AxisY);
0372       layerThickness = protoLayer.range(AxisDirection::AxisZ);
0373       break;
0374     }
0375     default:
0376       throw std::invalid_argument("Invalid binning value");
0377   }
0378 
0379   const double centerX = protoLayer.medium(AxisDirection::AxisX);
0380   const double centerY = protoLayer.medium(AxisDirection::AxisY);
0381   const double centerZ = protoLayer.medium(AxisDirection::AxisZ);
0382 
0383   ACTS_VERBOSE("Creating a plane Layer:");
0384   ACTS_VERBOSE(" - with layer center     = "
0385                << "(" << centerX << ", " << centerY << ", " << centerZ << ")");
0386   ACTS_VERBOSE(" - from X min/max   = "
0387                << protoLayer.min(AxisDirection::AxisX) << " / "
0388                << protoLayer.max(AxisDirection::AxisX));
0389   ACTS_VERBOSE(" - from Y min/max   = "
0390                << protoLayer.min(AxisDirection::AxisY) << " / "
0391                << protoLayer.max(AxisDirection::AxisY));
0392   ACTS_VERBOSE(" - with Z thickness = " << layerThickness);
0393   ACTS_VERBOSE("   - incl envelope  = " << protoLayer.envelope[aDir][0u]
0394                                         << " / "
0395                                         << protoLayer.envelope[aDir][1u]);
0396 
0397   // create the layer transforms if not given
0398   // we need to transform in case centerX/centerY/centerZ != 0, so that the
0399   // layer will be correctly defined
0400   Transform3 fullTransform = transform;
0401   if (fullTransform.isApprox(Transform3::Identity())) {
0402     fullTransform = Translation3(centerX, centerY, centerZ) * fullTransform;
0403     ACTS_VERBOSE(" - layer shift  = " << "(" << centerX << ", " << centerY
0404                                       << ", " << centerZ << ")");
0405   }
0406 
0407   std::unique_ptr<SurfaceArray> sArray;
0408   if (!surfaces.empty()) {
0409     sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnPlane(
0410         gctx, std::move(surfaces), bins1, bins2, aDir, protoLayer,
0411         fullTransform);
0412 
0413     checkBinning(gctx, *sArray);
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 bool LayerCreator::checkBinning(const GeometryContext& gctx,
0445                                 const SurfaceArray& sArray) const {
0446   // do consistency check: can we access all sensitive surfaces
0447   // through the binning? If not, surfaces get lost and the binning does not
0448   // work
0449 
0450   ACTS_VERBOSE("Performing consistency check");
0451 
0452   std::vector<const Surface*> surfaces = sArray.surfaces();
0453   std::set<const Surface*> sensitiveSurfaces(surfaces.begin(), surfaces.end());
0454   std::set<const Surface*> accessibleSurfaces;
0455   std::size_t nEmptyBins = 0;
0456   std::size_t nBinsChecked = 0;
0457 
0458   // iterate over all bins
0459   std::size_t size = sArray.size();
0460   for (std::size_t b = 0; b < size; ++b) {
0461     std::vector<const Surface*> binContent = sArray.at(b);
0462     // we don't check under/overflow bins
0463     if (!sArray.isValidBin(b)) {
0464       continue;
0465     }
0466     for (const auto& srf : binContent) {
0467       accessibleSurfaces.insert(srf);
0468     }
0469     if (binContent.empty()) {
0470       nEmptyBins++;
0471     }
0472     nBinsChecked++;
0473   }
0474 
0475   std::vector<const Surface*> diff;
0476   std::set_difference(sensitiveSurfaces.begin(), sensitiveSurfaces.end(),
0477                       accessibleSurfaces.begin(), accessibleSurfaces.end(),
0478                       std::inserter(diff, diff.begin()));
0479 
0480   ACTS_VERBOSE(" - Checked " << nBinsChecked << " valid bins");
0481 
0482   if (nEmptyBins > 0) {
0483     ACTS_VERBOSE(" -- Not all bins point to surface. " << nEmptyBins
0484                                                        << " empty");
0485   } else {
0486     ACTS_VERBOSE(" -- All bins point to a surface");
0487   }
0488 
0489   if (!diff.empty()) {
0490     ACTS_ERROR(
0491         " -- Not all sensitive surfaces are accessible through binning. "
0492         "sensitive: "
0493         << sensitiveSurfaces.size()
0494         << "    accessible: " << accessibleSurfaces.size());
0495 
0496     // print all inaccessibles
0497     ACTS_ERROR(" -- Inaccessible surfaces: ");
0498     for (const auto& srf : diff) {
0499       // have to choose AxisDirection here
0500       Vector3 ctr = srf->referencePosition(gctx, AxisDirection::AxisR);
0501       ACTS_ERROR(" Surface(x=" << ctr.x() << ", y=" << ctr.y()
0502                                << ", z=" << ctr.z() << ", r=" << perp(ctr)
0503                                << ", phi=" << phi(ctr) << ")");
0504     }
0505 
0506   } else {
0507     ACTS_VERBOSE(" -- All sensitive surfaces are accessible through binning.");
0508   }
0509 
0510   return diff.empty();
0511 }
0512 
0513 }  // namespace Acts