Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:11:23

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 <array>
0026 #include <iterator>
0027 #include <ostream>
0028 #include <set>
0029 #include <utility>
0030 
0031 namespace Acts {
0032 class PlanarBounds;
0033 }  // namespace Acts
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   // @todo check consistency
0045   // copy the configuration
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   // 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   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   // 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 = 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   // now return
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   // remaining layer parameters
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   // adjust the layer radius
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   // create the layer transforms if not given
0159   // we need to transform in case layerZ != 0, so that the layer will be
0160   // correctly defined using the halflength
0161   // create the layer transforms if not given
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   // create the surface array
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   // create the layer and push it back
0183   std::shared_ptr<const CylinderBounds> cBounds(
0184       new CylinderBounds(layerR, layerHalfZ));
0185 
0186   // create the layer
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   // now return
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   // adjust the layer radius
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   // create the layer transforms if not given
0233   Translation3 addTranslation(0., 0., 0.);
0234   if (transform.isApprox(Transform3::Identity())) {
0235     addTranslation = Translation3(0., 0., layerZ);
0236   }
0237   // create the surface array
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   // create the share disc bounds
0247   auto dBounds = std::make_shared<const RadialBounds>(
0248       protoLayer.min(AxisDirection::AxisR),
0249       protoLayer.max(AxisDirection::AxisR));
0250 
0251   // create the layers
0252   // we use the same transform here as for the layer itself
0253   // for disk this is fine since we don't bin in Z, so does not matter
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   // return the layer
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   // adjust the layer radius
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   // create the layer transforms if not given
0298   Translation3 addTranslation(0., 0., 0.);
0299   if (transform.isApprox(Transform3::Identity())) {
0300     addTranslation = Translation3(0., 0., layerZ);
0301   }
0302 
0303   // create the surface array
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   // create the shared disc bounds
0313   auto dBounds = std::make_shared<const RadialBounds>(
0314       protoLayer.min(AxisDirection::AxisR),
0315       protoLayer.max(AxisDirection::AxisR));
0316 
0317   // create the layers
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   // return the layer
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   // remaining layer parameters
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   // create the layer transforms if not given
0394   // we need to transform in case centerX/centerY/centerZ != 0, so that the
0395   // layer will be correctly defined
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   // create the layer and push it back
0412   auto pBounds = std::make_shared<RectangleBounds>(layerHalf1, layerHalf2);
0413 
0414   // create the layer
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   // now return
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   // do consistency check: can we access all sensitive surfaces
0442   // through the binning? If not, surfaces get lost and the binning does not
0443   // work
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   // iterate over all bins
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     // we don't check under/overflow bins
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     // print all inaccessibles
0491     ACTS_ERROR(" -- Inaccessible surfaces: ");
0492     for (const auto& srf : diff) {
0493       // have to choose AxisDirection here
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 }