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-2018 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/old/interface.hpp>
0011 #include <boost/test/tools/output_test_stream.hpp>
0012 #include <boost/test/unit_test.hpp>
0013 
0014 #include "Acts/Definitions/Algebra.hpp"
0015 #include "Acts/Definitions/Alignment.hpp"
0016 #include "Acts/Definitions/TrackParametrization.hpp"
0017 #include "Acts/EventData/ParticleHypothesis.hpp"
0018 #include "Acts/EventData/TrackParameters.hpp"
0019 #include "Acts/Geometry/GeometryContext.hpp"
0020 #include "Acts/Material/HomogeneousSurfaceMaterial.hpp"
0021 #include "Acts/Propagator/Propagator.hpp"
0022 #include "Acts/Propagator/StraightLineStepper.hpp"
0023 #include "Acts/Surfaces/BoundaryCheck.hpp"
0024 #include "Acts/Surfaces/LineBounds.hpp"
0025 #include "Acts/Surfaces/Surface.hpp"
0026 #include "Acts/Surfaces/SurfaceBounds.hpp"
0027 #include "Acts/Tests/CommonHelpers/DetectorElementStub.hpp"
0028 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0029 #include "Acts/Tests/CommonHelpers/LineSurfaceStub.hpp"
0030 #include "Acts/Tests/CommonHelpers/PredefinedMaterials.hpp"
0031 #include "Acts/Utilities/BinningType.hpp"
0032 #include "Acts/Utilities/Intersection.hpp"
0033 #include "Acts/Utilities/Result.hpp"
0034 #include "Acts/Utilities/UnitVectors.hpp"
0035 #include "Acts/Utilities/VectorHelpers.hpp"
0036 
0037 #include <algorithm>
0038 #include <cmath>
0039 #include <memory>
0040 #include <optional>
0041 #include <ostream>
0042 #include <stdexcept>
0043 #include <string>
0044 #include <tuple>
0045 #include <vector>
0046 
0047 namespace Acts {
0048 class AssertionFailureException;
0049 
0050 namespace Test {
0051 
0052 // Create a test context
0053 GeometryContext tgContext = GeometryContext();
0054 
0055 BOOST_AUTO_TEST_SUITE(Surfaces)
0056 
0057 /// Unit test for creating compliant/non-compliant LineSurface object
0058 BOOST_AUTO_TEST_CASE(LineSurface_Constructors_test) {
0059   // Default ctor is deleted
0060   // LineSurfaceStub l;
0061   // ctor with translation, radius, halfz
0062   Translation3 translation{0., 1., 2.};
0063   Transform3 transform(translation);
0064   auto pTransform = Transform3(translation);
0065   const double radius{2.0}, halfz{20.};
0066   BOOST_CHECK(LineSurfaceStub(pTransform, radius, halfz).constructedOk());
0067   // ctor with nullptr for LineBounds
0068   BOOST_CHECK(LineSurfaceStub(pTransform).constructedOk());
0069   // ctor with LineBounds
0070   auto pLineBounds = std::make_shared<const LineBounds>(2., 10.0);
0071   BOOST_CHECK(LineSurfaceStub(pTransform, pLineBounds).constructedOk());
0072   // ctor with LineBounds, detector element, Identifier
0073   auto pMaterial =
0074       std::make_shared<const HomogeneousSurfaceMaterial>(makePercentSlab());
0075   DetectorElementStub detElement{pTransform, pLineBounds, 0.2, pMaterial};
0076   BOOST_CHECK(LineSurfaceStub(pLineBounds, detElement).constructedOk());
0077   LineSurfaceStub lineToCopy(pTransform, 2.0, 20.);
0078   // Copy ctor
0079   BOOST_CHECK(LineSurfaceStub(lineToCopy).constructedOk());
0080   // Copied and transformed ctor
0081   BOOST_CHECK(
0082       LineSurfaceStub(tgContext, lineToCopy, transform).constructedOk());
0083 
0084   /// Construct with nullptr bounds
0085   DetectorElementStub detElem;
0086   BOOST_CHECK_THROW(LineSurfaceStub nullBounds(nullptr, detElem),
0087                     AssertionFailureException);
0088 
0089   BOOST_TEST_MESSAGE(
0090       "All LineSurface constructors are callable without problem");
0091 }
0092 
0093 /// Unit tests of all named methods
0094 BOOST_AUTO_TEST_CASE(LineSurface_allNamedMethods_test) {
0095   // binningPosition()
0096   Translation3 translation{0., 1., 2.};
0097   Transform3 transform(translation);
0098   LineSurfaceStub line(transform, 2.0, 20.);
0099   Vector3 referencePosition{0., 1., 2.};
0100   CHECK_CLOSE_ABS(referencePosition, line.binningPosition(tgContext, binX),
0101                   1e-6);
0102   //
0103   // bounds()
0104   auto pLineBounds = std::make_shared<const LineBounds>(2., 10.0);
0105   LineSurfaceStub boundedLine(transform, pLineBounds);
0106   const LineBounds& bounds =
0107       dynamic_cast<const LineBounds&>(boundedLine.bounds());
0108   BOOST_CHECK_EQUAL(bounds, LineBounds(2., 10.0));
0109   //
0110   // globalToLocal()
0111   Vector3 gpos{0., 1., 0.};
0112   const Vector3 mom{20., 0., 0.};  // needs more realistic parameters
0113   Vector2 localPosition =
0114       line.globalToLocal(tgContext, gpos, mom.normalized()).value();
0115   const Vector2 expectedResult{0, -2};
0116   CHECK_CLOSE_ABS(expectedResult, localPosition, 1e-6);
0117   //
0118   // intersection
0119   {
0120     const Vector3 direction{0., 1., 2.};
0121     BoundaryCheck bcheck(false);
0122     auto sfIntersection =
0123         line.intersect(tgContext, {0., 0., 0.}, direction.normalized(), bcheck)
0124             .closest();
0125     BOOST_CHECK(sfIntersection);
0126     Vector3 expectedIntersection(0, 1., 2.);
0127     CHECK_CLOSE_ABS(sfIntersection.position(), expectedIntersection,
0128                     1e-6);  // need more tests..
0129     BOOST_CHECK_EQUAL(sfIntersection.object(), &line);
0130   }
0131   //
0132   // isOnSurface
0133   const Vector3 insidePosition{0., 2.5, 0.};
0134   BOOST_CHECK(line.isOnSurface(tgContext, insidePosition, mom,
0135                                BoundaryCheck(false)));  // need better test here
0136   const Vector3 outsidePosition{100., 100., 200.};
0137   BOOST_CHECK(
0138       !line.isOnSurface(tgContext, outsidePosition, mom, BoundaryCheck(true)));
0139   //
0140   // localToGlobal
0141   Vector3 returnedGlobalPosition{0., 0., 0.};
0142   // Vector2 localPosition{0., 0.};
0143   const Vector3 momentum{300., 200., 0.};  // find better values!
0144   returnedGlobalPosition =
0145       line.localToGlobal(tgContext, localPosition, momentum.normalized());
0146   const Vector3 expectedGlobalPosition{0, 1, 0};
0147   CHECK_CLOSE_ABS(returnedGlobalPosition, expectedGlobalPosition, 1e-6);
0148   //
0149   // referenceFrame
0150   Vector3 globalPosition{0., 0., 0.};
0151   auto returnedRotationMatrix =
0152       line.referenceFrame(tgContext, globalPosition, momentum.normalized());
0153   double v0 = std::cos(std::atan(2. / 3.));
0154   double v1 = std::sin(std::atan(2. / 3.));
0155   RotationMatrix3 expectedRotationMatrix;
0156   expectedRotationMatrix << -v1, 0., v0, v0, 0., v1, 0., 1., -0.;
0157   // std::cout<<returnedRotationMatrix<<std::endl;
0158   // std::cout<<expectedRotationMatrix<<std::endl;
0159   CHECK_CLOSE_OR_SMALL(returnedRotationMatrix, expectedRotationMatrix, 1e-6,
0160                        1e-9);
0161   //
0162   // name()
0163   boost::test_tools::output_test_stream output;
0164   output << line.name();
0165   BOOST_CHECK(output.is_equal("Acts::LineSurface"));
0166   //
0167   // normal
0168   {
0169     Vector3 position{5, 5, 5};  // should be irrelevant
0170     Vector3 direction{1, 0, 0};
0171     CHECK_CLOSE_ABS(line.normal(tgContext, position, direction), direction,
0172                     1e-6);
0173   }
0174   {
0175     Vector3 position{5, 5, 5};  // should be irrelevant
0176     Vector3 direction = Vector3{1, 0, 0.1}.normalized();
0177     CHECK_CLOSE_ABS(line.normal(tgContext, position, direction),
0178                     Vector3::UnitX(), 1e-6);
0179   }
0180   {
0181     Vector3 position{5, 5, 5};  // should be irrelevant
0182     Vector3 direction{-1, 0, 0};
0183     CHECK_CLOSE_ABS(line.normal(tgContext, position, direction), direction,
0184                     1e-6);
0185   }
0186   {
0187     Vector3 position{5, 5, 5};  // should be irrelevant
0188     Vector3 direction{0, 1, 0};
0189     CHECK_CLOSE_ABS(line.normal(tgContext, position, direction), direction,
0190                     1e-6);
0191   }
0192   //
0193   // pathCorrection
0194   Vector3 any3DVector = Vector3::Random();
0195   CHECK_CLOSE_REL(line.pathCorrection(tgContext, any3DVector, any3DVector), 1.,
0196                   1e-6);
0197 }
0198 
0199 /// Unit test for testing LineSurface assignment
0200 BOOST_AUTO_TEST_CASE(LineSurface_assignment_test) {
0201   Translation3 translation{0., 1., 2.};
0202   Transform3 transform(translation);
0203   LineSurfaceStub originalLine(transform, 2.0, 20.);
0204   LineSurfaceStub assignedLine(transform, 1.0, 1.0);
0205   BOOST_CHECK(assignedLine != originalLine);  // operator != from base
0206   assignedLine = originalLine;
0207   BOOST_CHECK(assignedLine == originalLine);  // operator == from base
0208 }
0209 
0210 /// Unit test for testing LineSurface alignment derivatives
0211 BOOST_AUTO_TEST_CASE(LineSurfaceAlignment) {
0212   Translation3 translation{0., 1., 2.};
0213   Transform3 transform(translation);
0214   LineSurfaceStub line(transform, 2.0, 20.);
0215 
0216   const auto& rotation = transform.rotation();
0217   // The local frame z axis
0218   const Vector3 localZAxis = rotation.col(2);
0219   // Check the local z axis is aligned to global z axis
0220   CHECK_CLOSE_ABS(localZAxis, Vector3(0., 0., 1.), 1e-15);
0221 
0222   // Define the track (global) position and direction
0223   Vector3 globalPosition{1, 2, 4};
0224   Vector3 momentum{-1, 1, 1};
0225   Vector3 direction = momentum.normalized();
0226 
0227   // (a) Test the derivative of path length w.r.t. alignment parameters
0228   const AlignmentToPathMatrix& alignToPath =
0229       line.alignmentToPathDerivative(tgContext, globalPosition, direction);
0230   // The expected results
0231   AlignmentToPathMatrix expAlignToPath = AlignmentToPathMatrix::Zero();
0232   const double value = std::sqrt(3) / 2;
0233   expAlignToPath << -value, value, 0, -3 * value, -value, 0;
0234   // Check if the calculated derivative is as expected
0235   CHECK_CLOSE_ABS(alignToPath, expAlignToPath, 1e-10);
0236 
0237   // (b) Test the derivative of bound track parameters local position w.r.t.
0238   // position in local 3D Cartesian coordinates
0239   const auto& loc3DToLocBound =
0240       line.localCartesianToBoundLocalDerivative(tgContext, globalPosition);
0241   // Check if the result is as expected
0242   ActsMatrix<2, 3> expLoc3DToLocBound = ActsMatrix<2, 3>::Zero();
0243   expLoc3DToLocBound << 1 / std::sqrt(2), 1 / std::sqrt(2), 0, 0, 0, 1;
0244   CHECK_CLOSE_ABS(loc3DToLocBound, expLoc3DToLocBound, 1e-10);
0245 }
0246 
0247 BOOST_AUTO_TEST_CASE(LineSurfaceTransformRoundTrip) {
0248   LineSurfaceStub surface(Transform3::Identity());
0249 
0250   auto roundTrip = [&surface](const Vector3& pos, const Vector3& dir) {
0251     auto intersection = surface.intersect(tgContext, pos, dir).closest();
0252     Vector3 global = intersection.position();
0253     Vector2 local = *surface.globalToLocal(tgContext, global, dir);
0254     Vector3 global2 = surface.localToGlobal(tgContext, local, dir);
0255     return std::make_tuple(global, local, global2);
0256   };
0257 
0258   {
0259     Vector3 pos = {-0.02801, 0.00475611, 0.285106};
0260     Vector3 dir = Vector3(-0.03951, -0.221457, -0.564298).normalized();
0261 
0262     auto [global, local, global2] = roundTrip(pos, dir);
0263 
0264     CHECK_CLOSE_ABS(global, global2, 1e-10);
0265   }
0266 
0267   {
0268     Vector3 pos = {-64.2892, 65.2697, -0.839014};
0269     Vector3 dir = Vector3(-0.236602, -0.157616, 0.956786).normalized();
0270 
0271     auto [global, local, global2] = roundTrip(pos, dir);
0272 
0273     CHECK_CLOSE_ABS(global, global2, 1e-10);
0274   }
0275 }
0276 
0277 BOOST_AUTO_TEST_CASE(LineSurfaceTransformRoundTripEtaStability) {
0278   LineSurfaceStub surface(Transform3::Identity());
0279 
0280   // eta=6 is already crashing
0281   const std::vector<double> etas = {0, 1, 2, 3, 4, 5};
0282 
0283   for (double eta : etas) {
0284     Vector3 pca = {5, 0, 0};
0285     Vector3 dir = makeDirectionFromPhiEta(M_PI_2, eta);
0286     Vector3 pos = pca + dir;
0287 
0288     auto intersection = surface.intersect(tgContext, pos, dir).closest();
0289 
0290     Vector3 global = intersection.position();
0291     Vector2 local = *surface.globalToLocal(tgContext, global, dir);
0292     Vector3 global2 = surface.localToGlobal(tgContext, local, dir);
0293 
0294     CHECK_CLOSE_ABS(global, global2, 1e-10);
0295     CHECK_CLOSE_ABS(pca, global2, 1e-10);
0296   }
0297 }
0298 
0299 BOOST_AUTO_TEST_CASE(LineSurfaceIntersection) {
0300   using namespace Acts::UnitLiterals;
0301 
0302   double eps = 1e-10;
0303 
0304   Vector3 direction = Vector3(1, 1, 100).normalized();
0305   BoundVector boundVector;
0306   boundVector << 1_cm, 1_cm, VectorHelpers::phi(direction),
0307       VectorHelpers::theta(direction), 1, 0;
0308   double pathLimit = 1_cm;
0309 
0310   auto surface = std::make_shared<LineSurfaceStub>(Transform3::Identity());
0311 
0312   BoundTrackParameters initialParams{surface, boundVector, std::nullopt,
0313                                      ParticleHypothesis::pion()};
0314 
0315   Propagator<StraightLineStepper> propagator({});
0316 
0317   CurvilinearTrackParameters displacedParameters{
0318       Vector4::Zero(), Vector3::Zero(), 1, std::nullopt,
0319       ParticleHypothesis::pion()};
0320   {
0321     PropagatorOptions<> options(tgContext, {});
0322     options.direction = Acts::Direction::Backward;
0323     options.pathLimit = pathLimit;
0324 
0325     auto result = propagator.propagate(initialParams, options);
0326     BOOST_CHECK(result.ok());
0327     BOOST_CHECK(result.value().endParameters);
0328 
0329     displacedParameters = result.value().endParameters.value();
0330   }
0331 
0332   auto intersection =
0333       surface
0334           ->intersect(tgContext, displacedParameters.position(tgContext),
0335                       displacedParameters.direction())
0336           .closest();
0337   CHECK_CLOSE_ABS(intersection.pathLength(), pathLimit, eps);
0338 
0339   BoundTrackParameters endParameters{surface, BoundVector::Zero(), std::nullopt,
0340                                      ParticleHypothesis::pion()};
0341   {
0342     PropagatorOptions<> options(tgContext, {});
0343     options.direction = Acts::Direction::Forward;
0344     options.maxStepSize = 1_mm;
0345 
0346     auto result = propagator.propagate(displacedParameters, *surface, options);
0347     BOOST_CHECK(result.ok());
0348     BOOST_CHECK(result.value().endParameters);
0349     CHECK_CLOSE_ABS(result.value().pathLength, pathLimit, eps);
0350     endParameters = result.value().endParameters.value();
0351   }
0352 
0353   CHECK_CLOSE_ABS(initialParams.parameters(), endParameters.parameters(), eps);
0354 }
0355 
0356 BOOST_AUTO_TEST_SUITE_END()
0357 }  // namespace Test
0358 }  // namespace Acts