Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:11:28

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2017-2021 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 http://mozilla.org/MPL/2.0/.
0008 
0009 #include <boost/test/data/test_case.hpp>
0010 #include <boost/test/tools/output_test_stream.hpp>
0011 #include <boost/test/unit_test.hpp>
0012 
0013 #include "Acts/Definitions/Algebra.hpp"
0014 #include "Acts/Definitions/Alignment.hpp"
0015 #include "Acts/Definitions/Tolerance.hpp"
0016 #include "Acts/Definitions/TrackParametrization.hpp"
0017 #include "Acts/Definitions/Units.hpp"
0018 #include "Acts/Geometry/Extent.hpp"
0019 #include "Acts/Geometry/GeometryContext.hpp"
0020 #include "Acts/Geometry/Polyhedron.hpp"
0021 #include "Acts/Surfaces/AnnulusBounds.hpp"
0022 #include "Acts/Surfaces/DiscSurface.hpp"
0023 #include "Acts/Surfaces/RadialBounds.hpp"
0024 #include "Acts/Surfaces/Surface.hpp"
0025 #include "Acts/Surfaces/SurfaceBounds.hpp"
0026 #include "Acts/Tests/CommonHelpers/DetectorElementStub.hpp"
0027 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0028 #include "Acts/Utilities/BinningType.hpp"
0029 #include "Acts/Utilities/Helpers.hpp"
0030 #include "Acts/Utilities/Intersection.hpp"
0031 #include "Acts/Utilities/Result.hpp"
0032 
0033 #include <algorithm>
0034 #include <cmath>
0035 #include <initializer_list>
0036 #include <memory>
0037 #include <ostream>
0038 #include <string>
0039 #include <utility>
0040 
0041 namespace Acts {
0042 class AssertionFailureException;
0043 
0044 namespace Test {
0045 // Create a test context
0046 GeometryContext tgContext = GeometryContext();
0047 
0048 BOOST_AUTO_TEST_SUITE(Surfaces)
0049 /// Unit tests for creating DiscSurface object
0050 BOOST_AUTO_TEST_CASE(DiscSurfaceConstruction) {
0051   // default constructor is deleted
0052   // scaffolding...
0053   double rMin(1.0), rMax(5.0), halfPhiSector(M_PI / 8.);
0054   //
0055   /// Test DiscSurface constructor with default halfPhiSector
0056   BOOST_CHECK_NO_THROW(
0057       Surface::makeShared<DiscSurface>(Transform3::Identity(), rMin, rMax));
0058   //
0059   /// Test DiscSurface constructor with a transform specified
0060   Translation3 translation{0., 1., 2.};
0061   auto pTransform = Transform3(translation);
0062   BOOST_CHECK_NO_THROW(
0063       Surface::makeShared<DiscSurface>(pTransform, rMin, rMax, halfPhiSector));
0064   //
0065   /// Copy constructed DiscSurface
0066   auto anotherDiscSurface =
0067       Surface::makeShared<DiscSurface>(pTransform, rMin, rMax, halfPhiSector);
0068   // N.B. Just using
0069   // BOOST_CHECK_NO_THROW(Surface::makeShared<DiscSurface>(anotherDiscSurface))
0070   // tries to call
0071   // the (deleted) default constructor.
0072   auto copiedSurface = Surface::makeShared<DiscSurface>(*anotherDiscSurface);
0073   BOOST_TEST_MESSAGE("Copy constructed DiscSurface ok");
0074   //
0075   /// Copied and transformed DiscSurface
0076   BOOST_CHECK_NO_THROW(Surface::makeShared<DiscSurface>(
0077       tgContext, *anotherDiscSurface, pTransform));
0078 
0079   /// Construct with nullptr bounds
0080   DetectorElementStub detElem;
0081   BOOST_CHECK_THROW(
0082       auto nullBounds = Surface::makeShared<DiscSurface>(nullptr, detElem),
0083       AssertionFailureException);
0084 }
0085 
0086 /// Unit tests of all named methods
0087 BOOST_AUTO_TEST_CASE(DiscSurfaceProperties) {
0088   Vector3 origin3D{0, 0, 0};
0089   double rMin(1.0), rMax(5.0), halfPhiSector(M_PI / 8.);
0090   auto discSurfaceObject = Surface::makeShared<DiscSurface>(
0091       Transform3::Identity(), rMin, rMax, halfPhiSector);
0092   //
0093   /// Test type
0094   BOOST_CHECK_EQUAL(discSurfaceObject->type(), Surface::Disc);
0095   //
0096   /// Test normal, no local position specified
0097   Vector3 zAxis{0, 0, 1};
0098   BOOST_CHECK_EQUAL(discSurfaceObject->normal(tgContext), zAxis);
0099   //
0100   /// Test normal, local position specified
0101   Vector2 lpos(2.0, 0.05);
0102   BOOST_CHECK_EQUAL(discSurfaceObject->normal(tgContext, lpos), zAxis);
0103   //
0104   /// Test binningPosition
0105   // auto binningPosition=
0106   // discSurfaceObject.binningPosition(BinningValue::binRPhi );
0107   // std::cout<<binningPosition<<std::endl;
0108   BOOST_CHECK_EQUAL(
0109       discSurfaceObject->binningPosition(tgContext, BinningValue::binRPhi),
0110       origin3D);
0111   //
0112   /// Test bounds
0113   BOOST_CHECK_EQUAL(discSurfaceObject->bounds().type(), SurfaceBounds::eDisc);
0114   //
0115   Vector3 ignoredMomentum{0., 0., 0.};
0116   /// Test isOnSurface()
0117   Vector3 point3DNotInSector{0.0, 1.2, 0};
0118   Vector3 point3DOnSurface{1.2, 0.0, 0};
0119   BOOST_CHECK(!discSurfaceObject->isOnSurface(tgContext, point3DNotInSector,
0120                                               ignoredMomentum,
0121                                               BoundaryCheck(true)));  // passes
0122   BOOST_CHECK(discSurfaceObject->isOnSurface(tgContext, point3DOnSurface,
0123                                              ignoredMomentum,
0124                                              BoundaryCheck(true)));  // passes
0125   //
0126   /// Test localToGlobal
0127   Vector3 returnedPosition{10.9, 8.7, 6.5};
0128   Vector3 expectedPosition{1.2, 0, 0};
0129   Vector2 rPhiOnDisc{1.2, 0.0};
0130   Vector2 rPhiNotInSector{1.2, M_PI};  // outside sector at Phi=0, +/- pi/8
0131   returnedPosition =
0132       discSurfaceObject->localToGlobal(tgContext, rPhiOnDisc, ignoredMomentum);
0133   CHECK_CLOSE_ABS(returnedPosition, expectedPosition, 1e-6);
0134   //
0135   returnedPosition = discSurfaceObject->localToGlobal(
0136       tgContext, rPhiNotInSector, ignoredMomentum);
0137   Vector3 expectedNonPosition{-1.2, 0, 0};
0138   CHECK_CLOSE_ABS(returnedPosition, expectedNonPosition, 1e-6);
0139   //
0140   /// Test globalToLocal
0141   Vector2 returnedLocalPosition{33., 44.};
0142   Vector2 expectedLocalPosition{1.2, 0.0};
0143   returnedLocalPosition =
0144       discSurfaceObject
0145           ->globalToLocal(tgContext, point3DOnSurface, ignoredMomentum)
0146           .value();
0147   CHECK_CLOSE_ABS(returnedLocalPosition, expectedLocalPosition, 1e-6);
0148 
0149   // Global to local does not check inside bounds
0150   returnedLocalPosition =
0151       discSurfaceObject
0152           ->globalToLocal(tgContext, point3DNotInSector, ignoredMomentum)
0153           .value();
0154   //
0155   Vector3 pointOutsideR{0.0, 100., 0};
0156   returnedLocalPosition =
0157       discSurfaceObject
0158           ->globalToLocal(tgContext, pointOutsideR, ignoredMomentum)
0159           .value();
0160   //
0161   /// Test localPolarToCartesian
0162   Vector2 rPhi1_1{std::sqrt(2.), M_PI / 4.};
0163   Vector2 cartesian1_1{1., 1.};
0164   CHECK_CLOSE_REL(discSurfaceObject->localPolarToCartesian(rPhi1_1),
0165                   cartesian1_1, 1e-6);
0166   //
0167   /// Test localCartesianToPolar
0168   CHECK_CLOSE_REL(discSurfaceObject->localCartesianToPolar(cartesian1_1),
0169                   rPhi1_1, 1e-6);
0170   //
0171   /// Test localPolarToLocalCartesian
0172   CHECK_CLOSE_REL(discSurfaceObject->localPolarToLocalCartesian(rPhi1_1),
0173                   cartesian1_1, 1e-6);
0174   //
0175   /// Test localCartesianToGlobal
0176   Vector3 cartesian3D1_1{1., 1., 0.};
0177   CHECK_CLOSE_ABS(
0178       discSurfaceObject->localCartesianToGlobal(tgContext, cartesian1_1),
0179       cartesian3D1_1, 1e-6);
0180   //
0181   /// Test globalToLocalCartesian
0182   CHECK_CLOSE_REL(
0183       discSurfaceObject->globalToLocalCartesian(tgContext, cartesian3D1_1),
0184       cartesian1_1, 1e-6);
0185   //
0186   /// Test pathCorrection
0187   double projected3DMomentum = std::sqrt(3.) * 1.e6;
0188   Vector3 momentum{projected3DMomentum, projected3DMomentum,
0189                    projected3DMomentum};
0190   Vector3 ignoredPosition = discSurfaceObject->center(tgContext);
0191   CHECK_CLOSE_REL(discSurfaceObject->pathCorrection(tgContext, ignoredPosition,
0192                                                     momentum.normalized()),
0193                   std::sqrt(3), 0.01);
0194   //
0195   /// intersection test
0196   Vector3 globalPosition{1.2, 0.0, -10.};
0197   Vector3 direction{0., 0., 1.};  // must be normalised
0198   Vector3 expected{1.2, 0.0, 0.0};
0199 
0200   // intersect is a struct of (Vector3) position, pathLength, distance and
0201   // (bool) valid, it's contained in a Surface intersection
0202   auto sfIntersection = discSurfaceObject
0203                             ->intersect(tgContext, globalPosition, direction,
0204                                         BoundaryCheck(false))
0205                             .closest();
0206   Intersection3D expectedIntersect{Vector3{1.2, 0., 0.}, 10.,
0207                                    Intersection3D::Status::reachable};
0208   BOOST_CHECK(bool(sfIntersection));
0209   CHECK_CLOSE_ABS(sfIntersection.position(), expectedIntersect.position(),
0210                   1e-9);
0211   CHECK_CLOSE_ABS(sfIntersection.pathLength(), expectedIntersect.pathLength(),
0212                   1e-9);
0213   BOOST_CHECK_EQUAL(sfIntersection.object(), discSurfaceObject.get());
0214 
0215   //
0216   /// Test name
0217   boost::test_tools::output_test_stream nameOuput;
0218   nameOuput << discSurfaceObject->name();
0219   BOOST_CHECK(nameOuput.is_equal("Acts::DiscSurface"));
0220 }
0221 //
0222 /// Unit test for testing DiscSurface assignment and equality
0223 BOOST_AUTO_TEST_CASE(DiscSurfaceAssignment) {
0224   Vector3 origin3D{0, 0, 0};
0225   double rMin(1.0), rMax(5.0), halfPhiSector(M_PI / 8.);
0226   auto discSurfaceObject = Surface::makeShared<DiscSurface>(
0227       Transform3::Identity(), rMin, rMax, halfPhiSector);
0228   auto assignedDisc =
0229       Surface::makeShared<DiscSurface>(Transform3::Identity(), 2.2, 4.4, 0.07);
0230   //
0231   BOOST_CHECK_NO_THROW(*assignedDisc = *discSurfaceObject);
0232   BOOST_CHECK((*assignedDisc) == (*discSurfaceObject));
0233 }
0234 
0235 /// Unit test for testing DiscSurface assignment and equality
0236 BOOST_AUTO_TEST_CASE(DiscSurfaceExtent) {
0237   double rMin(1.0), rMax(5.0);
0238 
0239   auto pDisc =
0240       Surface::makeShared<DiscSurface>(Transform3::Identity(), 0., rMax);
0241   auto pDiscExtent = pDisc->polyhedronRepresentation(tgContext, 1).extent();
0242 
0243   CHECK_CLOSE_ABS(0., pDiscExtent.min(binZ), s_onSurfaceTolerance);
0244   CHECK_CLOSE_ABS(0., pDiscExtent.max(binZ), s_onSurfaceTolerance);
0245   CHECK_CLOSE_ABS(0., pDiscExtent.min(binR), s_onSurfaceTolerance);
0246   CHECK_CLOSE_ABS(rMax, pDiscExtent.max(binR), s_onSurfaceTolerance);
0247   CHECK_CLOSE_ABS(-rMax, pDiscExtent.min(binX), s_onSurfaceTolerance);
0248   CHECK_CLOSE_ABS(rMax, pDiscExtent.max(binX), s_onSurfaceTolerance);
0249   CHECK_CLOSE_ABS(-rMax, pDiscExtent.min(binY), s_onSurfaceTolerance);
0250   CHECK_CLOSE_ABS(rMax, pDiscExtent.max(binY), s_onSurfaceTolerance);
0251   CHECK_CLOSE_ABS(-M_PI, pDiscExtent.min(binPhi), s_onSurfaceTolerance);
0252   CHECK_CLOSE_ABS(M_PI, pDiscExtent.max(binPhi), s_onSurfaceTolerance);
0253 
0254   auto pRing =
0255       Surface::makeShared<DiscSurface>(Transform3::Identity(), rMin, rMax);
0256   auto pRingExtent = pRing->polyhedronRepresentation(tgContext, 1).extent();
0257 
0258   CHECK_CLOSE_ABS(0., pRingExtent.min(binZ), s_onSurfaceTolerance);
0259   CHECK_CLOSE_ABS(0., pRingExtent.max(binZ), s_onSurfaceTolerance);
0260   CHECK_CLOSE_ABS(rMin, pRingExtent.min(binR), s_onSurfaceTolerance);
0261   CHECK_CLOSE_ABS(rMax, pRingExtent.max(binR), s_onSurfaceTolerance);
0262   CHECK_CLOSE_ABS(-rMax, pRingExtent.min(binX), s_onSurfaceTolerance);
0263   CHECK_CLOSE_ABS(rMax, pRingExtent.max(binX), s_onSurfaceTolerance);
0264   CHECK_CLOSE_ABS(-rMax, pRingExtent.min(binY), s_onSurfaceTolerance);
0265   CHECK_CLOSE_ABS(rMax, pRingExtent.max(binY), s_onSurfaceTolerance);
0266 }
0267 
0268 /// Unit test for testing DiscSurface alignment derivatives
0269 BOOST_AUTO_TEST_CASE(DiscSurfaceAlignment) {
0270   Translation3 translation{0., 1., 2.};
0271   Transform3 transform(translation);
0272   double rMin(1.0), rMax(5.0), halfPhiSector(M_PI / 8.);
0273   auto discSurfaceObject =
0274       Surface::makeShared<DiscSurface>(transform, rMin, rMax, halfPhiSector);
0275 
0276   const auto& rotation = transform.rotation();
0277   // The local frame z axis
0278   const Vector3 localZAxis = rotation.col(2);
0279   // Check the local z axis is aligned to global z axis
0280   CHECK_CLOSE_ABS(localZAxis, Vector3(0., 0., 1.), 1e-15);
0281 
0282   // Define the track (global) position and direction
0283   Vector3 globalPosition{0, 4, 2};
0284   Vector3 momentum{0, 0, 1};
0285   Vector3 direction = momentum.normalized();
0286 
0287   // (a) Test the derivative of path length w.r.t. alignment parameters
0288   const AlignmentToPathMatrix& alignToPath =
0289       discSurfaceObject->alignmentToPathDerivative(tgContext, globalPosition,
0290                                                    direction);
0291   // The expected results
0292   AlignmentToPathMatrix expAlignToPath = AlignmentToPathMatrix::Zero();
0293   expAlignToPath << 0, 0, 1, 3, 0, 0;
0294   // Check if the calculated derivative is as expected
0295   CHECK_CLOSE_ABS(alignToPath, expAlignToPath, 1e-10);
0296 
0297   // (b) Test the derivative of bound track parameters local position w.r.t.
0298   // position in local 3D Cartesian coordinates
0299   const auto& loc3DToLocBound =
0300       discSurfaceObject->localCartesianToBoundLocalDerivative(tgContext,
0301                                                               globalPosition);
0302   // Check if the result is as expected
0303   ActsMatrix<2, 3> expLoc3DToLocBound = ActsMatrix<2, 3>::Zero();
0304   expLoc3DToLocBound << 0, 1, 0, -1.0 / 3, 0, 0;
0305   CHECK_CLOSE_ABS(loc3DToLocBound, expLoc3DToLocBound, 1e-10);
0306 }
0307 
0308 BOOST_AUTO_TEST_CASE(DiscSurfaceBinningPosition) {
0309   using namespace Acts::UnitLiterals;
0310   Vector3 s{5_mm, 7_mm, 10_cm};
0311   Transform3 trf;
0312   trf = Translation3(s) * AngleAxis3{0.5, Vector3::UnitZ()};
0313 
0314   double minR = 300;
0315   double maxR = 330;
0316 
0317   {
0318     // Radial Bounds
0319     auto bounds = std::make_shared<RadialBounds>(minR, maxR, M_PI / 8, 0.1);
0320     auto disc = Acts::Surface::makeShared<Acts::DiscSurface>(trf, bounds);
0321 
0322     Vector3 bp = disc->binningPosition(tgContext, binR);
0323     double r = (bounds->rMax() + bounds->rMin()) / 2.0;
0324     double phi = bounds->get(RadialBounds::eAveragePhi);
0325     Vector3 exp = Vector3{r * std::cos(phi), r * std::sin(phi), 0};
0326     exp = trf * exp;
0327 
0328     BOOST_CHECK_EQUAL(bp, exp);
0329     BOOST_CHECK_EQUAL(disc->binningPositionValue(tgContext, binR),
0330                       VectorHelpers::perp(exp));
0331 
0332     bp = disc->binningPosition(tgContext, binPhi);
0333     BOOST_CHECK_EQUAL(bp, exp);
0334     BOOST_CHECK_EQUAL(disc->binningPositionValue(tgContext, binPhi),
0335                       VectorHelpers::phi(exp));
0336 
0337     for (auto b : {binX, binY, binZ, binEta, binRPhi, binH, binMag}) {
0338       BOOST_TEST_CONTEXT("binValue: " << b) {
0339         BOOST_CHECK_EQUAL(disc->binningPosition(tgContext, b),
0340                           disc->center(tgContext));
0341       }
0342     }
0343   }
0344 
0345   {
0346     // Annulus Bounds
0347     double minPhiRel = -0.3;
0348     double maxPhiRel = 0.2;
0349     Vector2 origin{5_mm, 5_mm};
0350     auto bounds = std::make_shared<AnnulusBounds>(minR, maxR, minPhiRel,
0351                                                   maxPhiRel, origin);
0352 
0353     auto disc = Acts::Surface::makeShared<Acts::DiscSurface>(trf, bounds);
0354 
0355     Vector3 bp = disc->binningPosition(tgContext, binR);
0356     double r = (bounds->rMax() + bounds->rMin()) / 2.0;
0357     double phi = bounds->get(AnnulusBounds::eAveragePhi);
0358     Vector3 exp = Vector3{r * std::cos(phi), r * std::sin(phi), 0};
0359     exp = trf * exp;
0360 
0361     BOOST_CHECK_EQUAL(bp, exp);
0362 
0363     bp = disc->binningPosition(tgContext, binPhi);
0364     BOOST_CHECK_EQUAL(bp, exp);
0365 
0366     for (auto b : {binX, binY, binZ, binEta, binRPhi, binH, binMag}) {
0367       BOOST_TEST_CONTEXT("binValue: " << b) {
0368         BOOST_CHECK_EQUAL(disc->binningPosition(tgContext, b),
0369                           disc->center(tgContext));
0370       }
0371     }
0372   }
0373 }
0374 
0375 BOOST_AUTO_TEST_SUITE_END()
0376 
0377 }  // namespace Test
0378 
0379 }  // namespace Acts