Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-27 08:15:42

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/Utilities/AxisDefinitions.hpp"
0013 #include "Acts/Utilities/BinningData.hpp"
0014 #include "Acts/Utilities/BinningType.hpp"
0015 #include "Acts/Utilities/Diagnostics.hpp"
0016 #include "Acts/Utilities/IAxis.hpp"
0017 #include "Acts/Utilities/ProtoAxis.hpp"
0018 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0019 
0020 #include <cmath>
0021 #include <cstddef>
0022 #include <memory>
0023 #include <numbers>
0024 #include <utility>
0025 #include <vector>
0026 
0027 using namespace Acts;
0028 
0029 namespace ActsTests {
0030 
0031 // the test positions in 3D
0032 Vector3 xyzPosition(0.5, 1.5, 2.5);
0033 Vector3 xyzPositionOutside(30., -30., 200.);
0034 Vector3 phi0Position(0.5, 0., 2.5);
0035 Vector3 phiPihPosition(0., 1.5, 2.5);
0036 Vector3 eta0Position(0.5, 1.5, 0.);
0037 // the test positions in 2D
0038 Vector2 xyPosition(0.5, 1.5);
0039 Vector2 rphizPosition(0.1, 2.5);
0040 Vector2 rphiPosition(3.5, std::numbers::pi / 8.);
0041 
0042 // the binnings - equidistant
0043 // x/y/zData
0044 // bin boundaries
0045 // | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
0046 BinningData xData_eq(open, AxisDirection::AxisX, 10, 0., 10.);
0047 BinningData yData_eq(open, AxisDirection::AxisY, 10, 0., 10.);
0048 BinningData zData_eq(open, AxisDirection::AxisZ, 10, 0., 10.);
0049 // r/phi/rphiData
0050 // bin boundaries
0051 // | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
0052 BinningData rData_eq(open, AxisDirection::AxisR, 10, 0., 10.);
0053 // bin boundaries
0054 // > -PI | -3/5 PI | -1/5 PI | 1/5 PI | 3/5 PI | PI <
0055 BinningData phiData_eq(closed, AxisDirection::AxisPhi, 5, -std::numbers::pi,
0056                        std::numbers::pi);
0057 // BinningData rPhiData_eq(closed, AxisDirection::AxisRPhi, 5,
0058 // -std::numbers::pi, std::numbers::pi); h/etaData bin boundaries | 0 | 2 | 4 |
0059 // 6 | 8 | 10 | BinningData hData_eq(open, AxisDirection::AxisTheta, 5,
0060 // 0., 10.); | -2.5 | -1.5 | -0.5 | 0.5 | 1.5 | 2.5 |
0061 BinningData etaData_eq(open, AxisDirection::AxisEta, 5, -2.5, 2.5);
0062 
0063 // Fest equality operator
0064 BinningData xData_eq_copy(open, AxisDirection::AxisX, 10, 0., 10.);
0065 
0066 // the binnings - arbitrary
0067 std::vector<float> values = {0., 1., 2., 3., 4., 10.};
0068 // bin boundaries
0069 // | 0 | 1 | 2 | 3 | 4 | 10 |
0070 BinningData xData_arb(open, AxisDirection::AxisX, values);
0071 BinningData yData_arb(open, AxisDirection::AxisY, values);
0072 // | -PI |  -2 |  -1 |  1 |  2 |  PI |
0073 std::vector<float> phiValues = {-std::numbers::pi, -2., -1., 1., 2.,
0074                                 std::numbers::pi};
0075 BinningData phiData_arb(closed, AxisDirection::AxisPhi, phiValues);
0076 
0077 // the binnings - arbitrary when switching to binary search - for boundary
0078 // sizes >= 50
0079 std::size_t nBins_binary = 59;
0080 double valueMin = 0.;
0081 double phiMin = -std::numbers::pi;
0082 double delta = 0.5;
0083 double phiDelta = 0.1064;
0084 
0085 // the binning - substructure
0086 std::vector<float> sstr = {0., 1., 1.5, 2., 3.};
0087 // multiplicative
0088 auto xData_sstr_mult =
0089     std::make_unique<const BinningData>(open, AxisDirection::AxisX, sstr);
0090 // | 0 | 1 | 1.5 | 2 |  3 | 4 | 4.5 | 5 | 6 | 7 | 7.5 | 8 | 9 |
0091 BinningData xData_mult(open, AxisDirection::AxisX, 3, 0., 9.,
0092                        std::move(xData_sstr_mult));
0093 /// additive
0094 // | 0 | 1 | 1.5 | 2 |  3 | 4 | 5 |
0095 std::vector<float> main_sstr = {0., 3., 4., 5.};
0096 auto xData_sstr_add =
0097     std::make_unique<const BinningData>(open, AxisDirection::AxisX, sstr);
0098 BinningData xData_add(open, AxisDirection::AxisX, main_sstr,
0099                       std::move(xData_sstr_add));
0100 
0101 // enum AxisDirection { AxisDirection::AxisX, AxisDirection::AxisY,
0102 // AxisDirection::AxisZ, AxisDirection::AxisR, AxisDirection::AxisPhi,
0103 // AxisDirection::AxisRPhi, AxisDirection::AxisTheta, AxisDirection::AxisEta }
0104 //
0105 
0106 BOOST_AUTO_TEST_SUITE(UtilitiesSuite)
0107 
0108 // test the different binning values
0109 BOOST_AUTO_TEST_CASE(BinningData_AxisDirection) {
0110   // the binnings - arbitrary when switching to binary search - for boundary
0111   // sizes >= 50
0112   std::vector<float> values_binary;
0113   std::vector<float> phiValues_binary;
0114   for (std::size_t i = 0; i <= nBins_binary; i++) {
0115     values_binary.push_back(valueMin + i * delta);
0116     phiValues_binary.push_back(phiMin + i * phiDelta);
0117   }
0118   // bin boundaries when switching to binary search - for boundary sizes >= 50
0119   BinningData xData_arb_binary(open, AxisDirection::AxisX, values_binary);
0120   BinningData phiData_arb_binary(closed, AxisDirection::AxisPhi,
0121                                  phiValues_binary);
0122   /// x/y/zData
0123   /// check the global position requests
0124   // | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
0125   BOOST_CHECK_EQUAL(xData_eq.bins(), std::size_t{10});
0126   // | 0 | 1 | 2 | 3 | 4 | 10 |
0127   BOOST_CHECK_EQUAL(xData_arb.bins(), std::size_t{5});
0128   // | 0 | 1 | 1.5 | 2 | 3 | 4 | 4.5 | 5 | 6 | 7 | 7.5 | 8 | 9 |
0129   BOOST_CHECK_EQUAL(xData_mult.bins(), std::size_t{12});
0130   // | 0 | 1 | 1.5 | 2 |  3 | 4 | 5 |
0131   BOOST_CHECK_EQUAL(xData_add.bins(), std::size_t{6});
0132   BOOST_CHECK_EQUAL(xData_arb_binary.bins(), nBins_binary);
0133 
0134   BOOST_CHECK(xData_eq_copy == xData_eq_copy);
0135   BOOST_CHECK(!(xData_eq == yData_eq));
0136 
0137   /// check the global position requests
0138   BOOST_CHECK_EQUAL(xData_eq.value(xyzPosition), 0.5);
0139   BOOST_CHECK_EQUAL(yData_eq.value(xyzPosition), 1.5);
0140   BOOST_CHECK_EQUAL(zData_eq.value(xyzPosition), 2.5);
0141   BOOST_CHECK_EQUAL(xData_arb.value(xyzPosition), 0.5);
0142   BOOST_CHECK_EQUAL(xData_mult.value(xyzPosition), 0.5);
0143   BOOST_CHECK_EQUAL(xData_add.value(xyzPosition), 0.5);
0144   BOOST_CHECK_EQUAL(xData_arb_binary.value(xyzPosition), 0.5);
0145 
0146   /// check the local position requests
0147   BOOST_CHECK_EQUAL(xData_eq.value(xyPosition), 0.5);
0148   BOOST_CHECK_EQUAL(yData_eq.value(xyPosition), 1.5);
0149   BOOST_CHECK_EQUAL(zData_eq.value(rphizPosition), 2.5);
0150   BOOST_CHECK_EQUAL(xData_arb.value(xyPosition), 0.5);
0151   BOOST_CHECK_EQUAL(xData_mult.value(xyPosition), 0.5);
0152   BOOST_CHECK_EQUAL(xData_add.value(xyPosition), 0.5);
0153   BOOST_CHECK_EQUAL(xData_arb_binary.value(xyPosition), 0.5);
0154 
0155   // r/phi/rphiData
0156   CHECK_CLOSE_REL(rData_eq.value(xyzPosition), std::hypot(0.5, 1.5), 1e-5);
0157   BOOST_CHECK_EQUAL(rData_eq.value(rphiPosition), 3.5);
0158 
0159   CHECK_SMALL(phiData_eq.value(phi0Position), 1e-6 * std::numbers::pi);
0160   CHECK_CLOSE_REL(phiData_eq.value(phiPihPosition), std::numbers::pi / 2.,
0161                   1e-5);
0162 
0163   BOOST_CHECK_EQUAL(phiData_eq.bins(), std::size_t{5});
0164   BOOST_CHECK_EQUAL(phiData_arb.bins(), std::size_t{5});
0165   BOOST_CHECK_EQUAL(phiData_arb_binary.bins(), nBins_binary);
0166 
0167   // h/etaData
0168   CHECK_SMALL(etaData_eq.value(eta0Position), 1e-5);
0169 }
0170 
0171 // test bin values
0172 BOOST_AUTO_TEST_CASE(BinningData_bins) {
0173   // the binnings - arbitrary when switching to binary search - for boundary
0174   // sizes >= 50
0175   std::vector<float> values_binary;
0176   std::vector<float> phiValues_binary;
0177   for (std::size_t i = 0; i <= nBins_binary; i++) {
0178     values_binary.push_back(valueMin + i * delta);
0179     phiValues_binary.push_back(phiMin + i * phiDelta);
0180   }
0181   // bin boundaries when switching to binary search - for boundary sizes >= 50
0182   BinningData xData_arb_binary(open, AxisDirection::AxisX, values_binary);
0183   BinningData phiData_arb_binary(closed, AxisDirection::AxisPhi,
0184                                  phiValues_binary);
0185   /// x/y/zData
0186   /// check the global position requests
0187   // | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
0188   BOOST_CHECK_EQUAL(xData_eq.searchGlobal(xyzPosition), std::size_t{0});
0189   BOOST_CHECK_EQUAL(yData_eq.searchGlobal(xyzPosition), std::size_t{1});
0190   BOOST_CHECK_EQUAL(zData_eq.searchGlobal(xyzPosition), std::size_t{2});
0191   // | 0 | 1 | 2 | 3 | 4 | 10 |
0192   BOOST_CHECK_EQUAL(xData_arb.searchGlobal(xyzPosition), std::size_t{0});
0193   BOOST_CHECK_EQUAL(xData_arb.search(6.), std::size_t{4});
0194   BOOST_CHECK_EQUAL(xData_arb_binary.searchGlobal(xyzPosition), std::size_t{0});
0195   BOOST_CHECK_EQUAL(xData_arb_binary.search(50.), (nBins_binary - 1));
0196   // | 0 | 1 | 1.5 | 2 |  3 | 4 | 5 |
0197   BOOST_CHECK_EQUAL(xData_add.searchGlobal(xyzPosition), std::size_t{0});
0198   BOOST_CHECK_EQUAL(xData_add.searchGlobal(xyzPosition), std::size_t{0});
0199   BOOST_CHECK_EQUAL(xData_add.search(0.2), std::size_t{0});
0200   BOOST_CHECK_EQUAL(xData_add.search(1.2), std::size_t{1});
0201   BOOST_CHECK_EQUAL(xData_add.search(1.7), std::size_t{2});
0202   BOOST_CHECK_EQUAL(xData_add.search(2.5), std::size_t{3});
0203   BOOST_CHECK_EQUAL(xData_add.search(3.5), std::size_t{4});
0204   BOOST_CHECK_EQUAL(xData_add.search(4.2), std::size_t{5});
0205   BOOST_CHECK_EQUAL(xData_add.search(7.), std::size_t{5});
0206   // | 0 | 1 | 1.5 | 2 | 3 | 4 | 4.5 | 5 | 6 | 7 | 7.5 | 8 | 9 |
0207   BOOST_CHECK_EQUAL(xData_mult.searchGlobal(xyzPosition), std::size_t{0});
0208   BOOST_CHECK_EQUAL(xData_mult.search(0.2), std::size_t{0});
0209   BOOST_CHECK_EQUAL(xData_mult.search(1.2), std::size_t{1});
0210   BOOST_CHECK_EQUAL(xData_mult.search(1.7), std::size_t{2});
0211   BOOST_CHECK_EQUAL(xData_mult.search(2.5), std::size_t{3});
0212   BOOST_CHECK_EQUAL(xData_mult.search(3.5), std::size_t{4});
0213   BOOST_CHECK_EQUAL(xData_mult.search(4.2), std::size_t{5});
0214   BOOST_CHECK_EQUAL(xData_mult.search(4.7), std::size_t{6});
0215   BOOST_CHECK_EQUAL(xData_mult.search(5.7), std::size_t{7});
0216   BOOST_CHECK_EQUAL(xData_mult.search(6.5), std::size_t{8});
0217   BOOST_CHECK_EQUAL(xData_mult.search(7.2), std::size_t{9});
0218   BOOST_CHECK_EQUAL(xData_mult.search(7.7), std::size_t{10});
0219   BOOST_CHECK_EQUAL(xData_mult.search(8.1), std::size_t{11});
0220 
0221   /// check the local position requests
0222   BOOST_CHECK_EQUAL(xData_eq.searchLocal(xyPosition), std::size_t{0});
0223   BOOST_CHECK_EQUAL(yData_eq.searchLocal(xyPosition), std::size_t{1});
0224   BOOST_CHECK_EQUAL(zData_eq.searchLocal(rphizPosition), std::size_t{2});
0225   BOOST_CHECK_EQUAL(xData_arb.searchLocal(xyPosition), std::size_t{0});
0226   BOOST_CHECK_EQUAL(xData_arb_binary.searchLocal(xyPosition), std::size_t{0});
0227 
0228   // r/phi/rphiData
0229   BOOST_CHECK_EQUAL(rData_eq.searchGlobal(xyzPosition), std::size_t{1});
0230   BOOST_CHECK_EQUAL(rData_eq.searchLocal(rphiPosition), std::size_t{3});
0231   BOOST_CHECK_EQUAL(phiData_eq.searchGlobal(phi0Position), std::size_t{2});
0232   BOOST_CHECK_EQUAL(phiData_eq.searchGlobal(phiPihPosition), std::size_t{3});
0233   BOOST_CHECK_EQUAL(phiData_arb_binary.search(std::numbers::pi),
0234                     std::size_t{0});
0235 
0236   // h/etaData
0237   BOOST_CHECK_EQUAL(etaData_eq.searchGlobal(eta0Position), std::size_t{2});
0238 }
0239 
0240 // test inside/outside
0241 BOOST_AUTO_TEST_CASE(BinningData_inside_outside) {
0242   // the binnings - arbitrary when switching to binary search - for boundary
0243   // sizes >= 50
0244   std::vector<float> values_binary;
0245   std::vector<float> phiValues_binary;
0246   for (std::size_t i = 0; i <= nBins_binary; i++) {
0247     values_binary.push_back(valueMin + i * delta);
0248     phiValues_binary.push_back(phiMin + i * phiDelta);
0249   }
0250   // bin boundaries when switching to binary search - for boundary sizes >= 50
0251   BinningData xData_arb_binary(open, AxisDirection::AxisX, values_binary);
0252   BinningData phiData_arb_binary(closed, AxisDirection::AxisPhi,
0253                                  phiValues_binary);
0254   // check the global inside
0255   BOOST_CHECK_EQUAL(xData_eq.inside(xyzPosition), true);
0256   BOOST_CHECK_EQUAL(yData_eq.inside(xyzPosition), true);
0257   BOOST_CHECK_EQUAL(zData_eq.inside(xyzPosition), true);
0258   BOOST_CHECK_EQUAL(xData_arb.inside(xyzPosition), true);
0259   BOOST_CHECK_EQUAL(xData_add.inside(xyzPosition), true);
0260   BOOST_CHECK_EQUAL(xData_mult.inside(xyzPosition), true);
0261   BOOST_CHECK_EQUAL(xData_arb_binary.inside(xyzPosition), true);
0262 
0263   // check the global outside
0264   BOOST_CHECK_EQUAL(xData_eq.inside(xyzPositionOutside), false);
0265   BOOST_CHECK_EQUAL(yData_eq.inside(xyzPositionOutside), false);
0266   BOOST_CHECK_EQUAL(zData_eq.inside(xyzPositionOutside), false);
0267   BOOST_CHECK_EQUAL(xData_arb.inside(xyzPositionOutside), false);
0268   BOOST_CHECK_EQUAL(xData_add.inside(xyzPositionOutside), false);
0269   BOOST_CHECK_EQUAL(xData_mult.inside(xyzPositionOutside), false);
0270   BOOST_CHECK_EQUAL(xData_arb_binary.inside(xyzPositionOutside), false);
0271 
0272   // cthe local inside
0273   BOOST_CHECK_EQUAL(xData_eq.inside(xyPosition), true);
0274   BOOST_CHECK_EQUAL(yData_eq.inside(xyPosition), true);
0275   BOOST_CHECK_EQUAL(zData_eq.inside(rphizPosition), true);
0276 
0277   // r/phi/rphiData inside
0278   BOOST_CHECK_EQUAL(phiData_eq.inside(phi0Position), true);
0279   BOOST_CHECK_EQUAL(phiData_eq.inside(phiPihPosition), true);
0280   //// h/etaData
0281   BOOST_CHECK_EQUAL(etaData_eq.inside(eta0Position), true);
0282 }
0283 
0284 // test open/close
0285 BOOST_AUTO_TEST_CASE(BinningData_open_close) {
0286   // the binnings - arbitrary when switching to binary search - for boundary
0287   // sizes >= 50
0288   std::vector<float> values_binary;
0289   std::vector<float> phiValues_binary;
0290   for (std::size_t i = 0; i <= nBins_binary; i++) {
0291     values_binary.push_back(valueMin + i * delta);
0292     phiValues_binary.push_back(phiMin + i * phiDelta);
0293   }
0294   // bin boundaries when switching to binary search - for boundary sizes >= 50
0295   BinningData xData_arb_binary(open, AxisDirection::AxisX, values_binary);
0296   BinningData phiData_arb_binary(closed, AxisDirection::AxisPhi,
0297                                  phiValues_binary);
0298   // open values
0299   BOOST_CHECK_EQUAL(xData_eq.searchGlobal(xyzPositionOutside), std::size_t{9});
0300   BOOST_CHECK_EQUAL(yData_eq.searchGlobal(xyzPositionOutside), std::size_t{0});
0301   BOOST_CHECK_EQUAL(zData_eq.searchGlobal(xyzPositionOutside), std::size_t{9});
0302   BOOST_CHECK_EQUAL(xData_arb.searchGlobal(xyzPositionOutside) + 1,
0303                     xData_arb.bins());
0304   BOOST_CHECK_EQUAL(xData_arb_binary.searchGlobal(xyzPositionOutside) + 1,
0305                     xData_arb_binary.bins());
0306   BOOST_CHECK_EQUAL(yData_arb.searchGlobal(xyzPositionOutside), std::size_t{0});
0307 
0308   // closed values
0309   BOOST_CHECK_EQUAL(phiData_eq.search(-4.), std::size_t{4});
0310   BOOST_CHECK_EQUAL(phiData_eq.search(4.), std::size_t{0});
0311   BOOST_CHECK_EQUAL(phiData_arb.search(-4.), std::size_t{4});
0312   BOOST_CHECK_EQUAL(phiData_arb.search(4.), std::size_t{0});
0313   BOOST_CHECK_EQUAL(phiData_arb_binary.search(-4.), (nBins_binary - 1));
0314   BOOST_CHECK_EQUAL(phiData_arb_binary.search(4.), std::size_t{0});
0315 }
0316 
0317 // test boundaries
0318 BOOST_AUTO_TEST_CASE(BinningData_boundaries) {
0319   // open values
0320   std::vector<float> boundaries = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.};
0321   BOOST_CHECK_EQUAL_COLLECTIONS(xData_eq.boundaries().begin(),
0322                                 xData_eq.boundaries().end(), boundaries.begin(),
0323                                 boundaries.end());
0324 
0325   const float phiStep = std::numbers::pi * 2. / 5.;
0326   std::vector<float> phiBoundaries_eq;
0327 
0328   for (int i = 0; i <= 5; ++i) {
0329     phiBoundaries_eq.push_back(
0330         static_cast<float>(-std::numbers::pi + i * phiStep));
0331   }
0332 
0333   CHECK_CLOSE_REL(phiData_eq.boundaries(), phiBoundaries_eq, 1e-5);
0334 }
0335 
0336 // test bin center values
0337 // test boundaries
0338 BOOST_AUTO_TEST_CASE(BinningData_bincenter) {
0339   // the binnings - arbitrary when switching to binary search - for boundary
0340   // sizes >= 50
0341   std::vector<float> values_binary;
0342   std::vector<float> phiValues_binary;
0343   for (std::size_t i = 0; i <= nBins_binary; i++) {
0344     values_binary.push_back(valueMin + i * delta);
0345     phiValues_binary.push_back(phiMin + i * phiDelta);
0346   }
0347   // bin boundaries when switching to binary search - for boundary sizes >= 50
0348   BinningData xData_arb_binary(open, AxisDirection::AxisX, values_binary);
0349   BinningData phiData_arb_binary(closed, AxisDirection::AxisPhi,
0350                                  phiValues_binary);
0351   /// check the global position requests
0352   // | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
0353   BOOST_CHECK_EQUAL(xData_eq.center(3), 3.5);
0354   // | 0 | 1 | 2 | 3 | 4 | 10 |
0355   BOOST_CHECK_EQUAL(xData_arb.center(4), 7.);
0356   // | 0 | 1 | 1.5 | 2 |  3 | 4 | 5 |
0357   BOOST_CHECK_EQUAL(xData_add.center(0), 0.5);
0358   BOOST_CHECK_EQUAL(xData_add.center(1), 1.25);
0359   BOOST_CHECK_EQUAL(xData_add.center(4), 3.5);
0360   // | 0 | 1 | 1.5 | 2 | 3 | 4 | 4.5 | 5 | 6 | 7 | 7.5 | 8 | 9 |
0361   BOOST_CHECK_EQUAL(xData_mult.center(0), 0.5);
0362   BOOST_CHECK_EQUAL(xData_mult.center(1), 1.25);
0363   BOOST_CHECK_EQUAL(xData_mult.center(4), 3.5);
0364   BOOST_CHECK_EQUAL(xData_mult.center(10), 7.75);
0365   BOOST_CHECK_EQUAL(xData_mult.center(11), 8.5);
0366 
0367   BOOST_CHECK_EQUAL(xData_arb_binary.center(0), 0.5 * delta);
0368 
0369   // open values
0370   std::vector<float> center = {0.5, 1.5, 2.5, 3.5, 4.5,
0371                                5.5, 6.5, 7.5, 8.5, 9.5};
0372   for (std::size_t ib = 0; ib < center.size(); ++ib) {
0373     BOOST_CHECK_EQUAL(xData_eq.center(ib), center[ib]);
0374   }
0375 
0376   // running into rounding errors here
0377   const float phiStep = std::numbers::pi * 2. / 5.;
0378   std::vector<float> phiCenters_eq;
0379 
0380   for (int i = 0; i < 5; ++i) {
0381     phiCenters_eq.push_back(
0382         static_cast<float>(-std::numbers::pi + (i + 0.5) * phiStep));
0383   }
0384 
0385   for (std::size_t ib = 0; ib < phiCenters_eq.size(); ++ib) {
0386     CHECK_CLOSE_ABS(phiData_eq.center(ib), phiCenters_eq[ib], 1e-3);
0387   }
0388 }
0389 
0390 // special test for phi binning
0391 BOOST_AUTO_TEST_CASE(BinningData_phi_modules) {
0392   // n phi modules with phi boundary at -pi/+pi are checked above one module
0393   // expands over -pi/+pi
0394   const float deltaPhi = 0.1;
0395   BinningData phiData_mod(closed, AxisDirection::AxisPhi, 5,
0396                           -std::numbers::pi + deltaPhi,
0397                           std::numbers::pi + deltaPhi);
0398 
0399   const float phiStep = std::numbers::pi * 2. / 5.;
0400   std::vector<float> phiBoundaries_mod;
0401 
0402   for (int i = 0; i <= 5; ++i) {
0403     phiBoundaries_mod.push_back(
0404         static_cast<float>(-std::numbers::pi + i * phiStep) + deltaPhi);
0405   }
0406 
0407   // this is the boundary test
0408   CHECK_CLOSE_REL(phiData_mod.boundaries(), phiBoundaries_mod, 1e-5);
0409 
0410   // now test the bin jump 0/maxbin
0411 
0412   float firstAngle = (-std::numbers::pi + 1.5 * deltaPhi);
0413   Vector3 firstBin(std::cos(firstAngle), std::sin(firstAngle), 0.);
0414   BOOST_CHECK_EQUAL(phiData_mod.search(firstAngle), std::size_t{0});
0415   BOOST_CHECK_EQUAL(phiData_mod.searchGlobal(firstBin), std::size_t{0});
0416 
0417   float firstAngleNeg = (-std::numbers::pi + 0.5 * deltaPhi);
0418   Vector3 lastBinNeg(std::cos(firstAngleNeg), std::sin(firstAngleNeg), 0.);
0419   BOOST_CHECK_EQUAL(phiData_mod.search(firstAngleNeg), std::size_t{4});
0420   BOOST_CHECK_EQUAL(phiData_mod.searchGlobal(lastBinNeg), std::size_t{4});
0421 
0422   float lastAnglePos = (std::numbers::pi + 0.5 * deltaPhi);
0423   Vector3 lastBinPos(std::cos(lastAnglePos), std::sin(lastAnglePos), 0.);
0424   BOOST_CHECK_EQUAL(phiData_mod.search(lastAnglePos), std::size_t{4});
0425   BOOST_CHECK_EQUAL(phiData_mod.searchGlobal(lastBinPos), std::size_t{4});
0426 
0427   // now test the (remaining) phi scaling
0428   float underscaledAngle = -std::numbers::pi - 0.5 * deltaPhi;
0429   Vector3 underscaledPos(std::cos(underscaledAngle), std::sin(underscaledAngle),
0430                          0.);
0431   BOOST_CHECK_EQUAL(phiData_mod.search(underscaledAngle), std::size_t{4});
0432   BOOST_CHECK_EQUAL(phiData_mod.searchGlobal(underscaledPos), std::size_t{4});
0433 }
0434 
0435 // special test for phi binning
0436 BOOST_AUTO_TEST_CASE(BinningData_from_ProtoAxis) {
0437   using enum AxisDirection;
0438   using enum AxisBoundaryType;
0439 
0440   // The DirectedProtoAxis based constructor is deprecated but still covered
0441   ACTS_PUSH_IGNORE_DEPRECATED()
0442 
0443   // Bound, equidistant axis
0444   DirectedProtoAxis epab(AxisX, Bound, 0.0, 1.0, 10);
0445   BinningData bEpab(epab);
0446 
0447   BOOST_CHECK_EQUAL(bEpab.bins(), std::size_t{10});
0448   BOOST_CHECK_EQUAL(bEpab.min, 0.);
0449   BOOST_CHECK_EQUAL(bEpab.max, 1.);
0450   BOOST_CHECK(bEpab.binvalue == AxisX);
0451   BOOST_CHECK(bEpab.option == open);
0452   BOOST_CHECK(bEpab.type == equidistant);
0453 
0454   // Bound, equidistant axis, autorange
0455   DirectedProtoAxis epa(AxisY, Bound, 10);
0456   BinningData bEpa(epa);
0457   BOOST_CHECK(bEpa.binvalue == AxisY);
0458   BOOST_CHECK_EQUAL(bEpa.bins(), std::size_t{10});
0459   BOOST_CHECK(bEpa.option == open);
0460   BOOST_CHECK(bEpa.type == equidistant);
0461 
0462   // Bound, equidistant axis
0463   DirectedProtoAxis vpab(AxisZ, Bound, {0.0, 1.0, 10});
0464   BinningData bVpab(vpab);
0465   BOOST_CHECK(bVpab.binvalue == AxisZ);
0466   BOOST_CHECK_EQUAL(bVpab.bins(), std::size_t{2});
0467   BOOST_CHECK(bVpab.option == open);
0468   BOOST_CHECK(bVpab.type == arbitrary);
0469 
0470   ACTS_POP_IGNORE_DEPRECATED()
0471 }
0472 
0473 BOOST_AUTO_TEST_CASE(BinningData_from_IAxis) {
0474   using enum AxisDirection;
0475   using enum AxisBoundaryType;
0476 
0477   // Bound, equidistant axis carrying its direction
0478   auto eAxis = IAxis::createEquidistant(Bound, 0.0, 1.0, 10, AxisX);
0479   BinningData bEqui(*eAxis);
0480 
0481   BOOST_CHECK_EQUAL(bEqui.bins(), std::size_t{10});
0482   BOOST_CHECK_EQUAL(bEqui.min, 0.);
0483   BOOST_CHECK_EQUAL(bEqui.max, 1.);
0484   BOOST_CHECK(bEqui.binvalue == AxisX);
0485   BOOST_CHECK(bEqui.option == open);
0486   BOOST_CHECK(bEqui.type == equidistant);
0487 
0488   // Bound, variable axis carrying its direction
0489   auto vAxis = IAxis::createVariable(Bound, {0.0, 1.0, 10.}, AxisZ);
0490   BinningData bVar(*vAxis);
0491   BOOST_CHECK(bVar.binvalue == AxisZ);
0492   BOOST_CHECK_EQUAL(bVar.bins(), std::size_t{2});
0493   BOOST_CHECK(bVar.option == open);
0494   BOOST_CHECK(bVar.type == arbitrary);
0495 
0496   // An axis without direction is rejected
0497   auto nAxis = IAxis::createEquidistant(Bound, 0.0, 1.0, 10);
0498   BOOST_CHECK_THROW(BinningData{*nAxis}, std::invalid_argument);
0499 
0500   // Explicitly directed construction works without an axis direction
0501   BinningData bDir(AxisY, *nAxis);
0502   BOOST_CHECK(bDir.binvalue == AxisY);
0503   BOOST_CHECK_EQUAL(bDir.bins(), std::size_t{10});
0504 }
0505 
0506 BOOST_AUTO_TEST_SUITE_END()
0507 
0508 }  // namespace ActsTests