Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:03:57

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 <boost/test/unit_test.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/GeometryContext.hpp"
0016 #include "Acts/Geometry/LayerCreator.hpp"
0017 #include "Acts/Geometry/ProtoLayer.hpp"
0018 #include "Acts/Geometry/SurfaceArrayCreator.hpp"
0019 #include "Acts/Surfaces/CylinderBounds.hpp"
0020 #include "Acts/Surfaces/PlanarBounds.hpp"
0021 #include "Acts/Surfaces/PlaneSurface.hpp"
0022 #include "Acts/Surfaces/RadialBounds.hpp"
0023 #include "Acts/Surfaces/RectangleBounds.hpp"
0024 #include "Acts/Surfaces/Surface.hpp"
0025 #include "Acts/Surfaces/SurfaceArray.hpp"
0026 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0027 #include "Acts/Utilities/BinningType.hpp"
0028 #include "Acts/Utilities/IAxis.hpp"
0029 #include "Acts/Utilities/Logger.hpp"
0030 
0031 #include <cstddef>
0032 #include <fstream>
0033 #include <iomanip>
0034 #include <iostream>
0035 #include <memory>
0036 #include <numbers>
0037 #include <set>
0038 #include <string>
0039 #include <utility>
0040 #include <vector>
0041 
0042 #include <boost/format.hpp>
0043 
0044 namespace Acts::Test {
0045 
0046 // Create a test context
0047 GeometryContext tgContext = GeometryContext();
0048 
0049 using SrfVec = std::vector<std::shared_ptr<const Surface>>;
0050 
0051 void draw_surfaces(const SrfVec& surfaces, const std::string& fname) {
0052   std::ofstream os;
0053   os.open(fname);
0054 
0055   os << std::fixed << std::setprecision(4);
0056 
0057   std::size_t nVtx = 0;
0058   for (const auto& srfx : surfaces) {
0059     std::shared_ptr<const PlaneSurface> srf =
0060         std::dynamic_pointer_cast<const PlaneSurface>(srfx);
0061     const PlanarBounds* bounds =
0062         dynamic_cast<const PlanarBounds*>(&srf->bounds());
0063 
0064     for (const auto& vtxloc : bounds->vertices()) {
0065       Vector3 vtx =
0066           srf->transform(tgContext) * Vector3(vtxloc.x(), vtxloc.y(), 0);
0067       os << "v " << vtx.x() << " " << vtx.y() << " " << vtx.z() << "\n";
0068     }
0069 
0070     // connect them
0071     os << "f";
0072     for (std::size_t i = 1; i <= bounds->vertices().size(); ++i) {
0073       os << " " << nVtx + i;
0074     }
0075     os << "\n";
0076 
0077     nVtx += bounds->vertices().size();
0078   }
0079 
0080   os.close();
0081 }
0082 
0083 struct LayerCreatorFixture {
0084   std::shared_ptr<const SurfaceArrayCreator> p_SAC;
0085   std::shared_ptr<LayerCreator> p_LC;
0086 
0087   std::vector<std::shared_ptr<const Surface>> m_surfaces;
0088 
0089   LayerCreatorFixture() {
0090     p_SAC = std::make_shared<const SurfaceArrayCreator>(
0091         SurfaceArrayCreator::Config(),
0092         Acts::getDefaultLogger("SurfaceArrayCreator", Acts::Logging::VERBOSE));
0093     LayerCreator::Config cfg;
0094     cfg.surfaceArrayCreator = p_SAC;
0095     p_LC = std::make_shared<LayerCreator>(
0096         cfg, Acts::getDefaultLogger("LayerCreator", Acts::Logging::VERBOSE));
0097   }
0098 
0099   template <typename... Args>
0100   bool checkBinning(Args&&... args) {
0101     return p_LC->checkBinning(std::forward<Args>(args)...);
0102   }
0103 
0104   bool checkBinContentSize(const SurfaceArray* sArray, std::size_t n) {
0105     std::size_t nBins = sArray->size();
0106     bool result = true;
0107     for (std::size_t i = 0; i < nBins; ++i) {
0108       if (!sArray->isValidBin(i)) {
0109         continue;
0110       }
0111       std::vector<const Surface*> binContent = sArray->at(i);
0112       BOOST_TEST_INFO("Bin: " << i);
0113       BOOST_CHECK_EQUAL(binContent.size(), n);
0114       result = result && binContent.size() == n;
0115     }
0116 
0117     return result;
0118   }
0119 
0120   SrfVec fullPhiTestSurfacesEC(std::size_t n = 10, double shift = 0,
0121                                double zbase = 0, double r = 10) {
0122     SrfVec res;
0123 
0124     double phiStep = 2 * std::numbers::pi / n;
0125     for (std::size_t i = 0; i < n; ++i) {
0126       double z = zbase + ((i % 2 == 0) ? 1 : -1) * 0.2;
0127 
0128       Transform3 trans;
0129       trans.setIdentity();
0130       trans.rotate(Eigen::AngleAxisd(i * phiStep + shift, Vector3(0, 0, 1)));
0131       trans.translate(Vector3(r, 0, z));
0132 
0133       auto bounds = std::make_shared<const RectangleBounds>(2, 1);
0134       std::shared_ptr<PlaneSurface> srf =
0135           Surface::makeShared<PlaneSurface>(trans, bounds);
0136 
0137       res.push_back(srf);
0138       m_surfaces.push_back(
0139           std::move(srf));  // keep shared, will get destroyed at the end
0140     }
0141 
0142     return res;
0143   }
0144 
0145   SrfVec fullPhiTestSurfacesBRL(int n = 10, double shift = 0, double zbase = 0,
0146                                 double incl = std::numbers::pi / 9.,
0147                                 double w = 2, double h = 1.5) {
0148     SrfVec res;
0149 
0150     double phiStep = 2 * std::numbers::pi / n;
0151     for (int i = 0; i < n; ++i) {
0152       double z = zbase;
0153 
0154       Transform3 trans;
0155       trans.setIdentity();
0156       trans.rotate(Eigen::AngleAxisd(i * phiStep + shift, Vector3(0, 0, 1)));
0157       trans.translate(Vector3(10, 0, z));
0158       trans.rotate(Eigen::AngleAxisd(incl, Vector3(0, 0, 1)));
0159       trans.rotate(Eigen::AngleAxisd(std::numbers::pi / 2., Vector3(0, 1, 0)));
0160 
0161       auto bounds = std::make_shared<const RectangleBounds>(w, h);
0162       std::shared_ptr<PlaneSurface> srf =
0163           Surface::makeShared<PlaneSurface>(trans, bounds);
0164 
0165       res.push_back(srf);
0166       m_surfaces.push_back(
0167           std::move(srf));  // keep shared, will get destroyed at the end
0168     }
0169 
0170     return res;
0171   }
0172 
0173   SrfVec makeBarrel(int nPhi, int nZ, double w, double h) {
0174     double z0 = -(nZ - 1) * w;
0175     SrfVec res;
0176 
0177     for (int i = 0; i < nZ; i++) {
0178       double z = i * w * 2 + z0;
0179       std::cout << "z=" << z << std::endl;
0180       SrfVec ring =
0181           fullPhiTestSurfacesBRL(nPhi, 0, z, std::numbers::pi / 9., w, h);
0182       res.insert(res.end(), ring.begin(), ring.end());
0183     }
0184 
0185     return res;
0186   }
0187 
0188   std::pair<SrfVec, std::vector<std::pair<const Surface*, const Surface*>>>
0189   makeBarrelStagger(int nPhi, int nZ, double shift = 0,
0190                     double incl = std::numbers::pi / 9., double w = 2,
0191                     double h = 1.5) {
0192     double z0 = -(nZ - 1) * w;
0193     SrfVec res;
0194 
0195     std::vector<std::pair<const Surface*, const Surface*>> pairs;
0196 
0197     for (int i = 0; i < nZ; i++) {
0198       double z = i * w * 2 + z0;
0199 
0200       double phiStep = 2 * std::numbers::pi / nPhi;
0201       for (int j = 0; j < nPhi; ++j) {
0202         Transform3 trans;
0203         trans.setIdentity();
0204         trans.rotate(Eigen::AngleAxisd(j * phiStep + shift, Vector3(0, 0, 1)));
0205         trans.translate(Vector3(10, 0, z));
0206         trans.rotate(Eigen::AngleAxisd(incl, Vector3(0, 0, 1)));
0207         trans.rotate(
0208             Eigen::AngleAxisd(std::numbers::pi / 2., Vector3(0, 1, 0)));
0209 
0210         auto bounds = std::make_shared<const RectangleBounds>(w, h);
0211         std::shared_ptr<PlaneSurface> srfA =
0212             Surface::makeShared<PlaneSurface>(trans, bounds);
0213 
0214         Vector3 nrm = srfA->normal(tgContext);
0215         Transform3 transB = trans;
0216         transB.pretranslate(nrm * 0.1);
0217         std::shared_ptr<PlaneSurface> srfB =
0218             Surface::makeShared<PlaneSurface>(transB, bounds);
0219 
0220         pairs.push_back(std::make_pair(srfA.get(), srfB.get()));
0221 
0222         res.push_back(srfA);
0223         res.push_back(srfB);
0224         m_surfaces.push_back(std::move(srfA));
0225         m_surfaces.push_back(std::move(srfB));
0226       }
0227     }
0228 
0229     return {res, pairs};
0230   }
0231 };
0232 
0233 BOOST_AUTO_TEST_SUITE(Tools)
0234 
0235 BOOST_FIXTURE_TEST_CASE(LayerCreator_createCylinderLayer, LayerCreatorFixture) {
0236   std::vector<std::shared_ptr<const Surface>> srf;
0237 
0238   srf = makeBarrel(30, 7, 2, 1.5);
0239   draw_surfaces(srf, "LayerCreator_createCylinderLayer_BRL_1.obj");
0240 
0241   // CASE I
0242   double envR = 0.1, envZ = 0.5;
0243   ProtoLayer pl(tgContext, srf);
0244   pl.envelope[Acts::AxisDirection::AxisR] = {envR, envR};
0245   pl.envelope[Acts::AxisDirection::AxisZ] = {envZ, envZ};
0246   std::shared_ptr<CylinderLayer> layer =
0247       std::dynamic_pointer_cast<CylinderLayer>(
0248           p_LC->cylinderLayer(tgContext, srf, equidistant, equidistant, pl));
0249 
0250   //
0251   double rMax = 10.6071, rMin = 9.59111;  // empirical - w/o envelopes
0252   CHECK_CLOSE_REL(layer->thickness(), (rMax - rMin) + 2. * envR, 1e-3);
0253 
0254   const CylinderBounds* bounds = &layer->bounds();
0255   CHECK_CLOSE_REL(bounds->get(CylinderBounds::eR), (rMax + rMin) / 2., 1e-3);
0256   CHECK_CLOSE_REL(bounds->get(CylinderBounds::eHalfLengthZ), 14 + envZ, 1e-3);
0257   BOOST_CHECK(checkBinning(tgContext, *layer->surfaceArray()));
0258   auto axes = layer->surfaceArray()->getAxes();
0259   BOOST_CHECK_EQUAL(axes.at(0)->getNBins(), 30u);
0260   BOOST_CHECK_EQUAL(axes.at(1)->getNBins(), 7u);
0261   CHECK_CLOSE_REL(axes.at(0)->getMin(), -std::numbers::pi, 1e-3);
0262   CHECK_CLOSE_REL(axes.at(0)->getMax(), std::numbers::pi, 1e-3);
0263   CHECK_CLOSE_REL(axes.at(1)->getMin(), -14, 1e-3);
0264   CHECK_CLOSE_REL(axes.at(1)->getMax(), 14, 1e-3);
0265 
0266   // CASE II
0267 
0268   ProtoLayer pl2(tgContext, srf);
0269   pl2.envelope[Acts::AxisDirection::AxisR] = {envR, envR};
0270   pl2.envelope[Acts::AxisDirection::AxisZ] = {envZ, envZ};
0271   layer = std::dynamic_pointer_cast<CylinderLayer>(
0272       p_LC->cylinderLayer(tgContext, srf, 30, 7, pl2));
0273   CHECK_CLOSE_REL(layer->thickness(), (rMax - rMin) + 2 * envR, 1e-3);
0274   bounds = &layer->bounds();
0275   CHECK_CLOSE_REL(bounds->get(CylinderBounds::eR), (rMax + rMin) / 2., 1e-3);
0276   CHECK_CLOSE_REL(bounds->get(CylinderBounds::eHalfLengthZ), 14 + envZ, 1e-3);
0277   BOOST_CHECK(checkBinning(tgContext, *layer->surfaceArray()));
0278   axes = layer->surfaceArray()->getAxes();
0279   BOOST_CHECK_EQUAL(axes.at(0)->getNBins(), 30u);
0280   BOOST_CHECK_EQUAL(axes.at(1)->getNBins(), 7u);
0281   CHECK_CLOSE_REL(axes.at(0)->getMin(), -std::numbers::pi, 1e-3);
0282   CHECK_CLOSE_REL(axes.at(0)->getMax(), std::numbers::pi, 1e-3);
0283   CHECK_CLOSE_REL(axes.at(1)->getMin(), -14, 1e-3);
0284   CHECK_CLOSE_REL(axes.at(1)->getMax(), 14, 1e-3);
0285 
0286   layer = std::dynamic_pointer_cast<CylinderLayer>(
0287       p_LC->cylinderLayer(tgContext, srf, 13, 3, pl2));
0288   CHECK_CLOSE_REL(layer->thickness(), (rMax - rMin) + 2 * envR, 1e-3);
0289   bounds = &layer->bounds();
0290   CHECK_CLOSE_REL(bounds->get(CylinderBounds::eR), (rMax + rMin) / 2., 1e-3);
0291   CHECK_CLOSE_REL(bounds->get(CylinderBounds::eHalfLengthZ), 14 + envZ, 1e-3);
0292   // this succeeds despite sub-optimal binning
0293   // since we now have multientry bins
0294   BOOST_CHECK(checkBinning(tgContext, *layer->surfaceArray()));
0295   axes = layer->surfaceArray()->getAxes();
0296   BOOST_CHECK_EQUAL(axes.at(0)->getNBins(), 13u);
0297   BOOST_CHECK_EQUAL(axes.at(1)->getNBins(), 3u);
0298   CHECK_CLOSE_REL(axes.at(0)->getMin(), -std::numbers::pi, 1e-3);
0299   CHECK_CLOSE_REL(axes.at(0)->getMax(), std::numbers::pi, 1e-3);
0300   CHECK_CLOSE_REL(axes.at(1)->getMin(), -14, 1e-3);
0301   CHECK_CLOSE_REL(axes.at(1)->getMax(), 14, 1e-3);
0302 
0303   // CASE III
0304   ProtoLayer pl3;
0305   pl3.extent.range(Acts::AxisDirection::AxisR).set(1, 20);
0306   pl3.extent.range(Acts::AxisDirection::AxisZ).set(-25, 25);
0307   layer = std::dynamic_pointer_cast<CylinderLayer>(
0308       p_LC->cylinderLayer(tgContext, srf, equidistant, equidistant, pl3));
0309   CHECK_CLOSE_REL(layer->thickness(), 19, 1e-3);
0310   bounds = &layer->bounds();
0311   CHECK_CLOSE_REL(bounds->get(CylinderBounds::eR), 10.5, 1e-3);
0312   CHECK_CLOSE_REL(bounds->get(CylinderBounds::eHalfLengthZ), 25, 1e-3);
0313 
0314   // this should fail, b/c it's a completely inconvenient binning
0315   // but it succeeds despite sub-optimal binning
0316   // since we now have multientry bins
0317   BOOST_CHECK(checkBinning(tgContext, *layer->surfaceArray()));
0318 
0319   axes = layer->surfaceArray()->getAxes();
0320   BOOST_CHECK_EQUAL(axes.at(0)->getNBins(), 30u);
0321   BOOST_CHECK_EQUAL(axes.at(1)->getNBins(), 7u);
0322   CHECK_CLOSE_REL(axes.at(0)->getMin(), -std::numbers::pi, 1e-3);
0323   CHECK_CLOSE_REL(axes.at(0)->getMax(), std::numbers::pi, 1e-3);
0324   CHECK_CLOSE_REL(axes.at(1)->getMin(), -25, 1e-3);
0325   CHECK_CLOSE_REL(axes.at(1)->getMax(), 25, 1e-3);
0326 }
0327 
0328 BOOST_FIXTURE_TEST_CASE(LayerCreator_createDiscLayer, LayerCreatorFixture) {
0329   std::vector<std::shared_ptr<const Surface>> surfaces;
0330   auto ringa = fullPhiTestSurfacesEC(30, 0, 0, 10);
0331   surfaces.insert(surfaces.end(), ringa.begin(), ringa.end());
0332   auto ringb = fullPhiTestSurfacesEC(30, 0, 0, 15);
0333   surfaces.insert(surfaces.end(), ringb.begin(), ringb.end());
0334   auto ringc = fullPhiTestSurfacesEC(30, 0, 0, 20);
0335   surfaces.insert(surfaces.end(), ringc.begin(), ringc.end());
0336   draw_surfaces(surfaces, "LayerCreator_createDiscLayer_EC_1.obj");
0337 
0338   ProtoLayer pl(tgContext, surfaces);
0339   pl.extent.range(AxisDirection::AxisZ).set(-10, 10);
0340   pl.extent.range(AxisDirection::AxisR).set(5., 25.);
0341   std::shared_ptr<DiscLayer> layer = std::dynamic_pointer_cast<DiscLayer>(
0342       p_LC->discLayer(tgContext, surfaces, equidistant, equidistant, pl));
0343   CHECK_CLOSE_REL(layer->thickness(), 20, 1e-3);
0344   const RadialBounds* bounds =
0345       dynamic_cast<const RadialBounds*>(&layer->bounds());
0346   CHECK_CLOSE_REL(bounds->rMin(), 5, 1e-3);
0347   CHECK_CLOSE_REL(bounds->rMax(), 25, 1e-3);
0348   BOOST_CHECK(checkBinning(tgContext, *layer->surfaceArray()));
0349   auto axes = layer->surfaceArray()->getAxes();
0350   BOOST_CHECK_EQUAL(axes.at(0)->getNBins(), 3u);
0351   BOOST_CHECK_EQUAL(axes.at(1)->getNBins(), 30u);
0352   CHECK_CLOSE_REL(axes.at(0)->getMin(), 5, 1e-3);
0353   CHECK_CLOSE_REL(axes.at(0)->getMax(), 25, 1e-3);
0354   CHECK_CLOSE_REL(axes.at(1)->getMin(), -std::numbers::pi, 1e-3);
0355   CHECK_CLOSE_REL(axes.at(1)->getMax(), std::numbers::pi, 1e-3);
0356   checkBinContentSize(layer->surfaceArray(), 1);
0357 
0358   // check that it's applying a rotation transform to improve phi binning
0359   // BOOST_CHECK_NE(bu->transform(), nullptr);
0360   // double actAngle = ((*bu->transform()) * Vector3(1, 0, 0)).phi();
0361   // double expAngle = -2 * std::numbers::pi / 30 / 2.;
0362   // CHECK_CLOSE_REL(actAngle, expAngle, 1e-3);
0363 
0364   double envMinR = 1, envMaxR = 1, envZ = 5;
0365   std::size_t nBinsR = 3, nBinsPhi = 30;
0366   ProtoLayer pl2(tgContext, surfaces);
0367   pl2.envelope[AxisDirection::AxisR] = {envMinR, envMaxR};
0368   pl2.envelope[AxisDirection::AxisZ] = {envZ, envZ};
0369   layer = std::dynamic_pointer_cast<DiscLayer>(
0370       p_LC->discLayer(tgContext, surfaces, nBinsR, nBinsPhi, pl2));
0371 
0372   double rMin = 8, rMax = 22.0227;
0373   CHECK_CLOSE_REL(layer->thickness(), 0.4 + 2 * envZ, 1e-3);
0374   bounds = dynamic_cast<const RadialBounds*>(&layer->bounds());
0375   CHECK_CLOSE_REL(bounds->rMin(), rMin - envMinR, 1e-3);
0376   CHECK_CLOSE_REL(bounds->rMax(), rMax + envMaxR, 1e-3);
0377   BOOST_CHECK(checkBinning(tgContext, *layer->surfaceArray()));
0378   axes = layer->surfaceArray()->getAxes();
0379   BOOST_CHECK_EQUAL(axes.at(0)->getNBins(), nBinsR);
0380   BOOST_CHECK_EQUAL(axes.at(1)->getNBins(), nBinsPhi);
0381   CHECK_CLOSE_REL(axes.at(0)->getMin(), rMin, 1e-3);
0382   CHECK_CLOSE_REL(axes.at(0)->getMax(), rMax, 1e-3);
0383   CHECK_CLOSE_REL(axes.at(1)->getMin(), -std::numbers::pi, 1e-3);
0384   CHECK_CLOSE_REL(axes.at(1)->getMax(), std::numbers::pi, 1e-3);
0385   checkBinContentSize(layer->surfaceArray(), 1);
0386 
0387   // check that it's applying a rotation transform to improve phi binning
0388   // BOOST_CHECK_NE(bu->transform(), nullptr);
0389   // actAngle = ((*bu->transform()) * Vector3(1, 0, 0)).phi();
0390   // expAngle = -2 * std::numbers::pi / 30 / 2.;
0391   // CHECK_CLOSE_REL(actAngle, expAngle, 1e-3);
0392 
0393   layer = std::dynamic_pointer_cast<DiscLayer>(
0394       p_LC->discLayer(tgContext, surfaces, equidistant, equidistant, pl2));
0395   CHECK_CLOSE_REL(layer->thickness(), 0.4 + 2 * envZ, 1e-3);
0396   bounds = dynamic_cast<const RadialBounds*>(&layer->bounds());
0397   CHECK_CLOSE_REL(bounds->rMin(), rMin - envMinR, 1e-3);
0398   CHECK_CLOSE_REL(bounds->rMax(), rMax + envMaxR, 1e-3);
0399   BOOST_CHECK(checkBinning(tgContext, *layer->surfaceArray()));
0400   axes = layer->surfaceArray()->getAxes();
0401   BOOST_CHECK_EQUAL(axes.at(0)->getNBins(), nBinsR);
0402   BOOST_CHECK_EQUAL(axes.at(1)->getNBins(), nBinsPhi);
0403   CHECK_CLOSE_REL(axes.at(0)->getMin(), rMin, 1e-3);
0404   CHECK_CLOSE_REL(axes.at(0)->getMax(), rMax, 1e-3);
0405   CHECK_CLOSE_REL(axes.at(1)->getMin(), -std::numbers::pi, 1e-3);
0406   CHECK_CLOSE_REL(axes.at(1)->getMax(), std::numbers::pi, 1e-3);
0407   checkBinContentSize(layer->surfaceArray(), 1);
0408 
0409   // check that it's applying a rotation transform to improve phi binning
0410   // BOOST_CHECK_NE(bu->transform(), nullptr);
0411   // actAngle = ((*bu->transform()) * Vector3(1, 0, 0)).phi();
0412   // expAngle = -2 * std::numbers::pi / 30 / 2.;
0413   // CHECK_CLOSE_REL(actAngle, expAngle, 1e-3);
0414 }
0415 
0416 BOOST_FIXTURE_TEST_CASE(LayerCreator_barrelStagger, LayerCreatorFixture) {
0417   auto barrel = makeBarrelStagger(30, 7, 0, std::numbers::pi / 9.);
0418   auto brl = barrel.first;
0419   draw_surfaces(brl, "LayerCreator_barrelStagger.obj");
0420 
0421   double envR = 0, envZ = 0;
0422   ProtoLayer pl(tgContext, brl);
0423   pl.envelope[AxisDirection::AxisR] = {envR, envR};
0424   pl.envelope[AxisDirection::AxisZ] = {envZ, envZ};
0425   std::shared_ptr<CylinderLayer> layer =
0426       std::dynamic_pointer_cast<CylinderLayer>(
0427           p_LC->cylinderLayer(tgContext, brl, equidistant, equidistant, pl));
0428 
0429   auto axes = layer->surfaceArray()->getAxes();
0430   BOOST_CHECK_EQUAL(axes.at(0)->getNBins(), 30u);
0431   BOOST_CHECK_EQUAL(axes.at(1)->getNBins(), 7u);
0432 
0433   // check if binning is good!
0434   for (const auto& pr : barrel.second) {
0435     auto A = pr.first;
0436     auto B = pr.second;
0437 
0438     // std::cout << A->center().phi() << " ";
0439     // std::cout << B->center().phi() << std::endl;
0440     // std::cout << "dPHi = " << A->center().phi() - B->center().phi() <<
0441     // std::endl;
0442 
0443     Vector3 ctr = A->referencePosition(tgContext, AxisDirection::AxisR);
0444     auto binContent = layer->surfaceArray()->at(ctr);
0445     BOOST_CHECK_EQUAL(binContent.size(), 2u);
0446     std::set<const Surface*> act;
0447     act.insert(binContent[0]);
0448     act.insert(binContent[1]);
0449 
0450     std::set<const Surface*> exp;
0451     exp.insert(A);
0452     exp.insert(B);
0453     BOOST_CHECK(exp == act);
0454   }
0455 
0456   // checkBinning should also report everything is fine
0457   checkBinning(tgContext, *layer->surfaceArray());
0458 }
0459 
0460 BOOST_AUTO_TEST_SUITE_END()
0461 
0462 }  // namespace Acts::Test