Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-08 09:26:01

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/Surfaces/AnnulusBounds.hpp"
0013 #include "Acts/Surfaces/BoundaryTolerance.hpp"
0014 #include "Acts/Surfaces/SurfaceBounds.hpp"
0015 #include "Acts/Utilities/VectorHelpers.hpp"
0016 
0017 #include <algorithm>
0018 #include <array>
0019 #include <cmath>
0020 #include <numbers>
0021 #include <stdexcept>
0022 #include <vector>
0023 
0024 using namespace Acts;
0025 
0026 namespace ActsTests {
0027 
0028 BOOST_AUTO_TEST_SUITE(SurfacesSuite)
0029 
0030 const double minRadius = 7.2;
0031 const double maxRadius = 12.0;
0032 const double minPhi = 0.74195;
0033 const double maxPhi = 1.33970;
0034 
0035 const Vector2 offset(-2., 2.);
0036 
0037 // Unit tests for AnnulusBounds constructors
0038 BOOST_AUTO_TEST_CASE(AnnulusBoundsConstruction) {
0039   // Test construction with radii and default sector
0040   auto original = AnnulusBounds(minRadius, maxRadius, minPhi, maxPhi, offset);
0041   AnnulusBounds copied(original);
0042   BOOST_CHECK_EQUAL(original, copied);
0043 }
0044 
0045 // Unit tests for AnnulusBounds recreation
0046 BOOST_AUTO_TEST_CASE(AnnulusBoundsRecreation) {
0047   // Test construction with radii and default sector
0048   auto original = AnnulusBounds(minRadius, maxRadius, minPhi, maxPhi, offset);
0049   auto valvector = original.values();
0050   std::array<double, AnnulusBounds::eSize> values{};
0051   std::copy_n(valvector.begin(), AnnulusBounds::eSize, values.begin());
0052   AnnulusBounds recreated(values);
0053   BOOST_CHECK_EQUAL(original, recreated);
0054 }
0055 
0056 // Unit tests for AnnulusBounds exception throwing
0057 BOOST_AUTO_TEST_CASE(AnnulusBoundsExcpetion) {
0058   // Exception for negative inner radius
0059   BOOST_CHECK_THROW(AnnulusBounds(-1., maxRadius, minPhi, maxPhi, offset),
0060                     std::logic_error);
0061   // Exception for negative outer radius
0062   BOOST_CHECK_THROW(AnnulusBounds(minRadius, -1., minPhi, maxPhi, offset),
0063                     std::logic_error);
0064   // Exception for swapped radii
0065   BOOST_CHECK_THROW(AnnulusBounds(maxRadius, minRadius, minPhi, maxPhi, offset),
0066                     std::logic_error);
0067   // Exception for out of range min phi
0068   BOOST_CHECK_THROW(AnnulusBounds(minRadius, maxRadius, -4., maxPhi, offset),
0069                     std::logic_error);
0070   // Exception for out of range max phi
0071   BOOST_CHECK_THROW(AnnulusBounds(minRadius, maxRadius, minPhi, 4., offset),
0072                     std::logic_error);
0073   // Exception for out of range max phi
0074   BOOST_CHECK_THROW(AnnulusBounds(minRadius, maxRadius, maxPhi, minPhi, offset),
0075                     std::logic_error);
0076 }
0077 
0078 /// Unit tests for AnnulusBounds properties
0079 BOOST_AUTO_TEST_CASE(AnnulusBoundsProperties) {
0080   /// Test construction with radii and default sector
0081   AnnulusBounds aBounds(minRadius, maxRadius, minPhi, maxPhi, offset);
0082 
0083   /// Test type() (redundant; already used in constructor confirmation)
0084   BOOST_CHECK_EQUAL(aBounds.type(), SurfaceBounds::eAnnulus);
0085 
0086   /// Test positions inside/outside
0087   // - start from cartesian (from test drawing)
0088   Vector2 inSurfaceXY(7., 7.);
0089   Vector2 outsideXY1(5., 5.);
0090   Vector2 outsideXY2(10., 3.);
0091   Vector2 outsideXY3(10., 10.);
0092   Vector2 outsideXY4(4., 10.);
0093   std::vector<Vector2> testPoints = {inSurfaceXY, outsideXY1, outsideXY2,
0094                                      outsideXY3, outsideXY4};
0095 
0096   auto toStripFrame = [&](const Vector2& xy) -> Vector2 {
0097     auto shifted = xy + offset;
0098     double r = VectorHelpers::perp(shifted);
0099     double phi = VectorHelpers::phi(shifted);
0100     return Vector2(r, phi);
0101   };
0102 
0103   BOOST_CHECK(
0104       aBounds.inside(toStripFrame(inSurfaceXY), BoundaryTolerance::None()));
0105   BOOST_CHECK(
0106       !aBounds.inside(toStripFrame(outsideXY1), BoundaryTolerance::None()));
0107   BOOST_CHECK(
0108       !aBounds.inside(toStripFrame(outsideXY2), BoundaryTolerance::None()));
0109   BOOST_CHECK(
0110       !aBounds.inside(toStripFrame(outsideXY3), BoundaryTolerance::None()));
0111   BOOST_CHECK(
0112       !aBounds.inside(toStripFrame(outsideXY4), BoundaryTolerance::None()));
0113 
0114   // Check radial inside
0115   BOOST_CHECK(!aBounds.insideRadialBounds(0.5));
0116   BOOST_CHECK(aBounds.insideRadialBounds(9.));
0117   BOOST_CHECK(!aBounds.insideRadialBounds(18.));
0118 
0119   // Test rMin
0120   BOOST_CHECK_EQUAL(aBounds.get(AnnulusBounds::eMinR), minRadius);
0121   // Test rMax
0122   BOOST_CHECK_EQUAL(aBounds.get(AnnulusBounds::eMaxR), maxRadius);
0123   // Test phiMin
0124   BOOST_CHECK_EQUAL(aBounds.get(AnnulusBounds::eMinPhiRel), minPhi);
0125   // Test phiMax
0126   BOOST_CHECK_EQUAL(aBounds.get(AnnulusBounds::eMaxPhiRel), maxPhi);
0127 }
0128 
0129 /// Unit tests for AnnulusBounds vertices
0130 BOOST_AUTO_TEST_CASE(AnnulusBoundsVertices) {
0131   /// Test construction with radii and default sector
0132   AnnulusBounds aBounds(minRadius, maxRadius, minPhi, maxPhi, offset);
0133 
0134   // Retrieve the corners
0135   auto corners = aBounds.corners();
0136   BOOST_CHECK_EQUAL(corners.size(), 4);
0137 
0138   // Retrieve the vertices
0139   auto vertices = aBounds.vertices(0u);
0140   BOOST_CHECK_EQUAL(vertices.size(), 4);
0141 
0142   // Now generate with more segments
0143   unsigned int nQuarterSegments = 12;
0144   vertices = aBounds.vertices(nQuarterSegments);
0145   BOOST_CHECK_EQUAL(vertices.size(), 14u);
0146 }
0147 
0148 BOOST_AUTO_TEST_CASE(AnnulusBoundsNegativeTolerance) {
0149   AnnulusBounds aBounds(minRadius, maxRadius, minPhi, maxPhi, offset);
0150   double phiAverage = (minPhi + maxPhi) / 2;
0151 
0152   auto check = [&](const BoundaryTolerance& tolerance, const Vector2& point) {
0153     Vector2 pointAverage(point[0], phiAverage + point[1]);
0154     return aBounds.inside(pointAverage, tolerance);
0155   };
0156 
0157   double midRadius = (minRadius + maxRadius) / 2;
0158   double hlPhi = (maxPhi - minPhi) / 2;
0159 
0160   {
0161     auto tolerance = BoundaryTolerance::AbsoluteEuclidean(1);
0162 
0163     // Test points near radial boundaries
0164     BOOST_CHECK(!check(tolerance, {minRadius - 1.5, 0}));
0165     BOOST_CHECK(check(tolerance, {minRadius - 0.1, 0}));
0166     BOOST_CHECK(check(tolerance, {minRadius + 0.4, 0}));
0167     BOOST_CHECK(check(tolerance, {minRadius + 0.5, 0}));
0168     BOOST_CHECK(check(tolerance, {minRadius + 1.5, 0}));
0169 
0170     BOOST_CHECK(check(tolerance, {maxRadius - 1.5, 0}));
0171     BOOST_CHECK(check(tolerance, {maxRadius - 0.1, 0}));
0172     BOOST_CHECK(check(tolerance, {maxRadius + 0.3, 0}));
0173     BOOST_CHECK(check(tolerance, {maxRadius + 0.55, 0}));
0174     BOOST_CHECK(check(tolerance, {maxRadius + 1.2, 0}));
0175     BOOST_CHECK(!check(tolerance, {maxRadius + 1.7, 0}));
0176 
0177     // Check points near axial boundaries
0178     BOOST_CHECK(!check(tolerance, {midRadius, -hlPhi * 1.5}));
0179     BOOST_CHECK(check(tolerance, {midRadius, -hlPhi * 1.1}));
0180     BOOST_CHECK(check(tolerance, {midRadius, -hlPhi * 0.8}));
0181     BOOST_CHECK(check(tolerance, {midRadius, -hlPhi * 0.5}));
0182 
0183     BOOST_CHECK(check(tolerance, {midRadius, hlPhi * 0.5}));
0184     BOOST_CHECK(check(tolerance, {midRadius, hlPhi * 0.8}));
0185     BOOST_CHECK(check(tolerance, {midRadius, hlPhi * 1.1}));
0186     BOOST_CHECK(!check(tolerance, {midRadius, hlPhi * 1.5}));
0187   }
0188 
0189   {
0190     auto tolerance = BoundaryTolerance::AbsoluteEuclidean(-1);
0191 
0192     // Test points near radial boundaries
0193     BOOST_CHECK(!check(tolerance, {minRadius - 1.5, 0}));
0194     BOOST_CHECK(!check(tolerance, {minRadius - 0.1, 0}));
0195     BOOST_CHECK(!check(tolerance, {minRadius + 0.4, 0}));
0196     BOOST_CHECK(!check(tolerance, {minRadius + 0.5, 0}));
0197     BOOST_CHECK(check(tolerance, {minRadius + 1.5, 0}));
0198 
0199     BOOST_CHECK(check(tolerance, {maxRadius - 1.5, 0}));
0200     BOOST_CHECK(!check(tolerance, {maxRadius - 0.1, 0}));
0201     BOOST_CHECK(!check(tolerance, {maxRadius + 0.3, 0}));
0202     BOOST_CHECK(!check(tolerance, {maxRadius + 0.55, 0}));
0203     BOOST_CHECK(!check(tolerance, {maxRadius + 1.2, 0}));
0204     BOOST_CHECK(!check(tolerance, {maxRadius + 1.7, 0}));
0205 
0206     // Check points near axial boundaries
0207     BOOST_CHECK(!check(tolerance, {midRadius, -hlPhi * 1.5}));
0208     BOOST_CHECK(!check(tolerance, {midRadius, -hlPhi * 1.1}));
0209     BOOST_CHECK(!check(tolerance, {midRadius, -hlPhi * 0.8}));
0210     BOOST_CHECK(check(tolerance, {midRadius, -hlPhi * 0.5}));
0211 
0212     BOOST_CHECK(check(tolerance, {midRadius, hlPhi * 0.5}));
0213     BOOST_CHECK(!check(tolerance, {midRadius, hlPhi * 0.8}));
0214     BOOST_CHECK(!check(tolerance, {midRadius, hlPhi * 1.1}));
0215     BOOST_CHECK(!check(tolerance, {midRadius, hlPhi * 1.5}));
0216   }
0217 
0218   {
0219     auto tolerance =
0220         BoundaryTolerance::Chi2Bound(SquareMatrix2::Identity(), 0.1);
0221 
0222     // Test points near radial boundaries
0223     BOOST_CHECK(!check(tolerance, {minRadius - 1.5, 0}));
0224     BOOST_CHECK(check(tolerance, {minRadius - 0.1, 0}));
0225     BOOST_CHECK(check(tolerance, {minRadius + 0.4, 0}));
0226     BOOST_CHECK(check(tolerance, {minRadius + 0.5, 0}));
0227     BOOST_CHECK(check(tolerance, {minRadius + 1.5, 0}));
0228 
0229     BOOST_CHECK(check(tolerance, {maxRadius - 1.5, 0}));
0230     BOOST_CHECK(check(tolerance, {maxRadius - 0.1, 0}));
0231     BOOST_CHECK(check(tolerance, {maxRadius + 0.3, 0}));
0232     BOOST_CHECK(check(tolerance, {maxRadius + 0.55, 0}));
0233     BOOST_CHECK(!check(tolerance, {maxRadius + 1.2, 0}));
0234     BOOST_CHECK(!check(tolerance, {maxRadius + 1.7, 0}));
0235 
0236     // Check points near axial boundaries
0237     BOOST_CHECK(check(tolerance, {midRadius, -hlPhi * 1.5}));
0238     BOOST_CHECK(check(tolerance, {midRadius, -hlPhi * 1.1}));
0239     BOOST_CHECK(check(tolerance, {midRadius, -hlPhi * 0.8}));
0240     BOOST_CHECK(check(tolerance, {midRadius, -hlPhi * 0.5}));
0241 
0242     BOOST_CHECK(check(tolerance, {midRadius, hlPhi * 0.5}));
0243     BOOST_CHECK(check(tolerance, {midRadius, hlPhi * 0.8}));
0244     BOOST_CHECK(check(tolerance, {midRadius, hlPhi * 1.1}));
0245     BOOST_CHECK(check(tolerance, {midRadius, hlPhi * 1.5}));
0246   }
0247 
0248   {
0249     auto tolerance =
0250         BoundaryTolerance::Chi2Bound(SquareMatrix2::Identity(), -0.1);
0251 
0252     // Test points near radial boundaries
0253     BOOST_CHECK(!check(tolerance, {minRadius - 1.5, 0}));
0254     BOOST_CHECK(!check(tolerance, {minRadius - 0.1, 0}));
0255     BOOST_CHECK(!check(tolerance, {minRadius + 0.4, 0}));
0256     BOOST_CHECK(!check(tolerance, {minRadius + 0.5, 0}));
0257     BOOST_CHECK(check(tolerance, {minRadius + 1.5, 0}));
0258 
0259     BOOST_CHECK(check(tolerance, {maxRadius - 1.5, 0}));
0260     BOOST_CHECK(check(tolerance, {maxRadius - 0.1, 0}));
0261     BOOST_CHECK(!check(tolerance, {maxRadius + 0.3, 0}));
0262     BOOST_CHECK(!check(tolerance, {maxRadius + 0.55, 0}));
0263     BOOST_CHECK(!check(tolerance, {maxRadius + 1.2, 0}));
0264     BOOST_CHECK(!check(tolerance, {maxRadius + 1.7, 0}));
0265 
0266     // Check points near axial boundaries
0267     BOOST_CHECK(!check(tolerance, {midRadius, -hlPhi * 1.5}));
0268     BOOST_CHECK(!check(tolerance, {midRadius, -hlPhi * 1.1}));
0269     BOOST_CHECK(!check(tolerance, {midRadius, -hlPhi * 0.8}));
0270     BOOST_CHECK(!check(tolerance, {midRadius, -hlPhi * 0.5}));
0271 
0272     BOOST_CHECK(!check(tolerance, {midRadius, hlPhi * 0.5}));
0273     BOOST_CHECK(!check(tolerance, {midRadius, hlPhi * 0.8}));
0274     BOOST_CHECK(!check(tolerance, {midRadius, hlPhi * 1.1}));
0275     BOOST_CHECK(!check(tolerance, {midRadius, hlPhi * 1.5}));
0276   }
0277 }
0278 
0279 BOOST_AUTO_TEST_CASE(AnnulusBoundsCenter) {
0280   // Test annulus bounds center calculation
0281   AnnulusBounds annulus(minRadius, maxRadius, minPhi, maxPhi, offset);
0282   Vector2 center = annulus.center();
0283 
0284   // The center should be inside the annulus bounds
0285   BOOST_CHECK(annulus.inside(center));
0286 
0287   // Test with symmetric annulus (no offset)
0288   Vector2 noOffset(0., 0.);
0289   AnnulusBounds symmetricAnnulus(minRadius, maxRadius, minPhi, maxPhi,
0290                                  noOffset);
0291   Vector2 symmetricCenter = symmetricAnnulus.center();
0292 
0293   // For symmetric case, center should also be inside bounds
0294   BOOST_CHECK(symmetricAnnulus.inside(symmetricCenter));
0295 
0296   // The center should be in polar coordinates (r, phi) in strip system
0297   // Verify that r component is reasonable (between min and max radius)
0298   BOOST_CHECK(symmetricCenter.x() >= minRadius);
0299   BOOST_CHECK(symmetricCenter.x() <= maxRadius);
0300 
0301   // Verify that phi component is within phi range
0302   BOOST_CHECK(symmetricCenter.y() >= minPhi);
0303   BOOST_CHECK(symmetricCenter.y() <= maxPhi);
0304 
0305   // Test with non-zero average phi to verify proper rotation handling
0306   double avgPhi = 0.5;  // Non-zero average phi
0307   AnnulusBounds rotatedAnnulus(minRadius, maxRadius, minPhi, maxPhi, noOffset,
0308                                avgPhi);
0309   Vector2 rotatedCenter = rotatedAnnulus.center();
0310 
0311   // The center should still be inside the bounds after rotation
0312   BOOST_CHECK(rotatedAnnulus.inside(rotatedCenter));
0313 
0314   // Center should be in strip polar coordinates
0315   BOOST_CHECK(rotatedCenter.x() >= minRadius);
0316   BOOST_CHECK(rotatedCenter.x() <= maxRadius);
0317 }
0318 
0319 BOOST_AUTO_TEST_CASE(AnnulusBoundsCoversFullAzimuth) {
0320   // A typical stereo module sector does not cover the full azimuth
0321   BOOST_CHECK(!AnnulusBounds(minRadius, maxRadius, minPhi, maxPhi, offset)
0322                    .coversFullAzimuth());
0323 
0324   // radian_sym wraps into [-pi, pi), so the widest annulus spans from -pi to
0325   // just below pi
0326   BOOST_CHECK(AnnulusBounds(minRadius, maxRadius, -std::numbers::pi,
0327                             std::numbers::pi - 1e-12, offset)
0328                   .coversFullAzimuth());
0329 
0330   // A gap wider than the tolerance is not the full azimuth
0331   BOOST_CHECK(!AnnulusBounds(minRadius, maxRadius, -std::numbers::pi,
0332                              std::numbers::pi - 1e-8, offset)
0333                    .coversFullAzimuth());
0334 
0335   // Half a turn is not the full azimuth either
0336   BOOST_CHECK(!AnnulusBounds(minRadius, maxRadius, -std::numbers::pi / 2.,
0337                              std::numbers::pi / 2., offset)
0338                    .coversFullAzimuth());
0339 }
0340 
0341 BOOST_AUTO_TEST_SUITE_END()
0342 
0343 }  // namespace ActsTests