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/output_test_stream.hpp>
0011 #include <boost/test/unit_test.hpp>
0012 
0013 #include "Acts/Definitions/Algebra.hpp"
0014 #include "Acts/Definitions/Tolerance.hpp"
0015 #include "Acts/Definitions/Units.hpp"
0016 #include "Acts/Geometry/Extent.hpp"
0017 #include "Acts/Geometry/GeometryContext.hpp"
0018 #include "Acts/Geometry/Polyhedron.hpp"
0019 #include "Acts/Surfaces/CylinderBounds.hpp"
0020 #include "Acts/Surfaces/CylinderSurface.hpp"
0021 #include "Acts/Surfaces/Surface.hpp"
0022 #include "Acts/Surfaces/SurfaceBounds.hpp"
0023 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0024 #include "Acts/Utilities/BinningType.hpp"
0025 #include "Acts/Utilities/Helpers.hpp"
0026 #include "Acts/Utilities/Intersection.hpp"
0027 #include "Acts/Utilities/Result.hpp"
0028 
0029 #include <algorithm>
0030 #include <cmath>
0031 #include <initializer_list>
0032 #include <memory>
0033 #include <ostream>
0034 #include <string>
0035 #include <utility>
0036 
0037 namespace Acts {
0038 class AssertionFailureException;
0039 }  // namespace Acts
0040 
0041 namespace Acts::Test {
0042 
0043 // Create a test context
0044 GeometryContext testContext = GeometryContext();
0045 
0046 BOOST_AUTO_TEST_SUITE(CylinderSurfaces)
0047 /// Unit test for creating compliant/non-compliant CylinderSurface object
0048 BOOST_AUTO_TEST_CASE(CylinderSurfaceConstruction) {
0049   // CylinderSurface default constructor is deleted
0050   //
0051   /// Constructor with transform, radius and halfZ
0052   double radius(1.0), halfZ(10.), halfPhiSector(M_PI / 8.);
0053   Translation3 translation{0., 1., 2.};
0054   auto pTransform = Transform3(translation);
0055   BOOST_CHECK_EQUAL(
0056       Surface::makeShared<CylinderSurface>(pTransform, radius, halfZ)->type(),
0057       Surface::Cylinder);
0058   //
0059   /// Constructor with transform pointer, radius, halfZ and halfPhiSector
0060   BOOST_CHECK_EQUAL(Surface::makeShared<CylinderSurface>(pTransform, radius,
0061                                                          halfZ, halfPhiSector)
0062                         ->type(),
0063                     Surface::Cylinder);
0064 
0065   /// Constructor with transform and CylinderBounds pointer
0066   auto pCylinderBounds = std::make_shared<const CylinderBounds>(radius, halfZ);
0067   BOOST_CHECK_EQUAL(
0068       Surface::makeShared<CylinderSurface>(pTransform, pCylinderBounds)->type(),
0069       Surface::Cylinder);
0070   //
0071   //
0072   /// Copy constructor
0073   auto cylinderSurfaceObject =
0074       Surface::makeShared<CylinderSurface>(pTransform, radius, halfZ);
0075   auto copiedCylinderSurface =
0076       Surface::makeShared<CylinderSurface>(*cylinderSurfaceObject);
0077   BOOST_CHECK_EQUAL(copiedCylinderSurface->type(), Surface::Cylinder);
0078   BOOST_CHECK(*copiedCylinderSurface == *cylinderSurfaceObject);
0079   //
0080   /// Copied and transformed
0081   auto copiedTransformedCylinderSurface = Surface::makeShared<CylinderSurface>(
0082       testContext, *cylinderSurfaceObject, pTransform);
0083   BOOST_CHECK_EQUAL(copiedTransformedCylinderSurface->type(),
0084                     Surface::Cylinder);
0085 
0086   /// Construct with nullptr bounds
0087   BOOST_CHECK_THROW(auto nullBounds = Surface::makeShared<CylinderSurface>(
0088                         Transform3::Identity(), nullptr),
0089                     AssertionFailureException);
0090 }
0091 //
0092 /// Unit test for testing CylinderSurface properties
0093 BOOST_AUTO_TEST_CASE(CylinderSurfaceProperties) {
0094   /// Test clone method
0095   double radius(1.0), halfZ(10.);
0096   Translation3 translation{0., 1., 2.};
0097   auto pTransform = Transform3(translation);
0098   auto cylinderSurfaceObject =
0099       Surface::makeShared<CylinderSurface>(pTransform, radius, halfZ);
0100   //
0101   /// Test type (redundant)
0102   BOOST_CHECK_EQUAL(cylinderSurfaceObject->type(), Surface::Cylinder);
0103   //
0104   /// Test binningPosition
0105   Vector3 binningPosition{0., 1., 2.};
0106   CHECK_CLOSE_ABS(
0107       cylinderSurfaceObject->binningPosition(testContext, BinningValue::binPhi),
0108       binningPosition, 1e-9);
0109   //
0110   /// Test referenceFrame
0111   double rootHalf = std::sqrt(0.5);
0112   Vector3 globalPosition{rootHalf, 1. - rootHalf, 0.};
0113   Vector3 globalPositionZ{rootHalf, 1. - rootHalf, 2.0};
0114   Vector3 momentum{15., 15., 15.};
0115   Vector3 momentum2{6.6, -3., 2.};
0116   RotationMatrix3 expectedFrame;
0117   expectedFrame << rootHalf, 0., rootHalf, rootHalf, 0., -rootHalf, 0., 1., 0.;
0118   // check without shift
0119   CHECK_CLOSE_OR_SMALL(cylinderSurfaceObject->referenceFrame(
0120                            testContext, globalPosition, momentum),
0121                        expectedFrame, 1e-6, 1e-9);
0122   // check with shift and different momentum
0123   CHECK_CLOSE_OR_SMALL(cylinderSurfaceObject->referenceFrame(
0124                            testContext, globalPositionZ, momentum2),
0125                        expectedFrame, 1e-6, 1e-9);
0126   //
0127   /// Test normal, given 3D position
0128   Vector3 origin{0., 0., 0.};
0129   Vector3 normal3D = {0., -1., 0.};
0130   CHECK_CLOSE_ABS(cylinderSurfaceObject->normal(testContext, origin), normal3D,
0131                   1e-9);
0132 
0133   Vector3 pos45deg = {rootHalf, 1 + rootHalf, 0.};
0134   Vector3 pos45degZ = {rootHalf, 1 + rootHalf, 4.};
0135   Vector3 normal45deg = {rootHalf, rootHalf, 0.};
0136   // test the normal vector
0137   CHECK_CLOSE_ABS(cylinderSurfaceObject->normal(testContext, pos45deg),
0138                   normal45deg, 1e-6 * rootHalf);
0139   // test that the normal vector is independent of z coordinate
0140   CHECK_CLOSE_ABS(cylinderSurfaceObject->normal(testContext, pos45degZ),
0141                   normal45deg, 1e-6 * rootHalf);
0142   //
0143   /// Test normal given 2D rphi position
0144   Vector2 positionPiBy2(1.0, 0.);
0145   Vector3 normalAtPiBy2{std::cos(1.), std::sin(1.), 0.};
0146   CHECK_CLOSE_ABS(cylinderSurfaceObject->normal(testContext, positionPiBy2),
0147                   normalAtPiBy2, 1e-9);
0148 
0149   //
0150   /// Test rotational symmetry axis
0151   Vector3 symmetryAxis{0., 0., 1.};
0152   CHECK_CLOSE_ABS(cylinderSurfaceObject->rotSymmetryAxis(testContext),
0153                   symmetryAxis, 1e-9);
0154   //
0155   /// Test bounds
0156   BOOST_CHECK_EQUAL(cylinderSurfaceObject->bounds().type(),
0157                     SurfaceBounds::eCylinder);
0158   //
0159   /// Test localToGlobal
0160   Vector2 localPosition{0., 0.};
0161   globalPosition = cylinderSurfaceObject->localToGlobal(
0162       testContext, localPosition, momentum);
0163   Vector3 expectedPosition{1, 1, 2};
0164   BOOST_CHECK_EQUAL(globalPosition, expectedPosition);
0165   //
0166   /// Testing globalToLocal
0167   localPosition = cylinderSurfaceObject
0168                       ->globalToLocal(testContext, globalPosition, momentum)
0169                       .value();
0170   Vector2 expectedLocalPosition{0., 0.};
0171   BOOST_CHECK_EQUAL(localPosition, expectedLocalPosition);
0172   //
0173   /// Test isOnSurface
0174   Vector3 offSurface{100, 1, 2};
0175   BOOST_CHECK(cylinderSurfaceObject->isOnSurface(
0176       testContext, globalPosition, momentum, BoundaryCheck(true)));
0177   BOOST_CHECK(!cylinderSurfaceObject->isOnSurface(
0178       testContext, offSurface, momentum, BoundaryCheck(true)));
0179   //
0180   /// intersection test
0181   Vector3 direction{-1., 0, 0};
0182   auto sfIntersection = cylinderSurfaceObject->intersect(
0183       testContext, offSurface, direction, BoundaryCheck(false));
0184   Intersection3D expectedIntersect{Vector3{1, 1, 2}, 99.,
0185                                    Intersection3D::Status::reachable};
0186   BOOST_CHECK(sfIntersection[0]);
0187   CHECK_CLOSE_ABS(sfIntersection[0].position(), expectedIntersect.position(),
0188                   1e-9);
0189   CHECK_CLOSE_ABS(sfIntersection[0].pathLength(),
0190                   expectedIntersect.pathLength(), 1e-9);
0191   // there is a second solution & and it should be valid
0192   BOOST_CHECK(sfIntersection[1]);
0193   // And it's path should be further away then the primary solution
0194   double pn = sfIntersection[0].pathLength();
0195   double pa = sfIntersection[1].pathLength();
0196   BOOST_CHECK_LT(std::abs(pn), std::abs(pa));
0197   BOOST_CHECK_EQUAL(sfIntersection.object(), cylinderSurfaceObject.get());
0198 
0199   //
0200   /// Test pathCorrection
0201   CHECK_CLOSE_REL(cylinderSurfaceObject->pathCorrection(testContext, offSurface,
0202                                                         momentum.normalized()),
0203                   std::sqrt(3.), 0.01);
0204   //
0205   /// Test name
0206   BOOST_CHECK_EQUAL(cylinderSurfaceObject->name(),
0207                     std::string("Acts::CylinderSurface"));
0208   //
0209   /// Test dump
0210   boost::test_tools::output_test_stream dumpOuput;
0211   cylinderSurfaceObject->toStream(testContext, dumpOuput);
0212   BOOST_CHECK(
0213       dumpOuput.is_equal("Acts::CylinderSurface\n\
0214      Center position  (x, y, z) = (0.0000, 1.0000, 2.0000)\n\
0215      Rotation:             colX = (1.000000, 0.000000, 0.000000)\n\
0216                            colY = (0.000000, 1.000000, 0.000000)\n\
0217                            colZ = (0.000000, 0.000000, 1.000000)\n\
0218      Bounds  : Acts::CylinderBounds: (radius, halfLengthZ, halfPhiSector, averagePhi, bevelMinZ, bevelMaxZ) = (1.0000000, 10.0000000, 3.1415927, 0.0000000, 0.0000000, 0.0000000)"));
0219 }
0220 
0221 BOOST_AUTO_TEST_CASE(CylinderSurfaceEqualityOperators) {
0222   double radius(1.0), halfZ(10.);
0223   Translation3 translation{0., 1., 2.};
0224   auto pTransform = Transform3(translation);
0225   auto cylinderSurfaceObject =
0226       Surface::makeShared<CylinderSurface>(pTransform, radius, halfZ);
0227   //
0228   auto cylinderSurfaceObject2 =
0229       Surface::makeShared<CylinderSurface>(pTransform, radius, halfZ);
0230   //
0231   /// Test equality operator
0232   BOOST_CHECK(*cylinderSurfaceObject == *cylinderSurfaceObject2);
0233   //
0234   BOOST_TEST_CHECKPOINT(
0235       "Create and then assign a CylinderSurface object to the existing one");
0236   /// Test assignment
0237   auto assignedCylinderSurface =
0238       Surface::makeShared<CylinderSurface>(Transform3::Identity(), 6.6, 5.4);
0239   *assignedCylinderSurface = *cylinderSurfaceObject;
0240   /// Test equality of assigned to original
0241   BOOST_CHECK(*assignedCylinderSurface == *cylinderSurfaceObject);
0242 }
0243 
0244 /// Unit test for testing CylinderSurface properties
0245 BOOST_AUTO_TEST_CASE(CylinderSurfaceExtent) {
0246   // Some radius and half length
0247   double radius(1.0), halfZ(10.);
0248   Translation3 translation{0., 0., 2.};
0249   auto pTransform = Transform3(translation);
0250   auto cylinderSurface =
0251       Surface::makeShared<CylinderSurface>(pTransform, radius, halfZ);
0252   // The Extent, let's measure it
0253   auto cylinderExtent =
0254       cylinderSurface->polyhedronRepresentation(testContext, 1).extent();
0255 
0256   CHECK_CLOSE_ABS(-8, cylinderExtent.min(binZ), s_onSurfaceTolerance);
0257   CHECK_CLOSE_ABS(12, cylinderExtent.max(binZ), s_onSurfaceTolerance);
0258   CHECK_CLOSE_ABS(radius, cylinderExtent.min(binR), s_onSurfaceTolerance);
0259   CHECK_CLOSE_ABS(radius, cylinderExtent.max(binR), s_onSurfaceTolerance);
0260   CHECK_CLOSE_ABS(-radius, cylinderExtent.min(binX), s_onSurfaceTolerance);
0261   CHECK_CLOSE_ABS(radius, cylinderExtent.max(binX), s_onSurfaceTolerance);
0262   CHECK_CLOSE_ABS(-radius, cylinderExtent.min(binY), s_onSurfaceTolerance);
0263   CHECK_CLOSE_ABS(radius, cylinderExtent.max(binY), s_onSurfaceTolerance);
0264 }
0265 
0266 /// Unit test for testing CylinderSurface alignment derivatives
0267 BOOST_AUTO_TEST_CASE(CylinderSurfaceAlignment) {
0268   double radius(1.0), halfZ(10.);
0269   Translation3 translation{0., 1., 2.};
0270   auto pTransform = Transform3(translation);
0271   auto cylinderSurfaceObject =
0272       Surface::makeShared<CylinderSurface>(pTransform, radius, halfZ);
0273 
0274   const auto& rotation = pTransform.rotation();
0275   // The local frame z axis
0276   const Vector3 localZAxis = rotation.col(2);
0277   // Check the local z axis is aligned to global z axis
0278   CHECK_CLOSE_ABS(localZAxis, Vector3(0., 0., 1.), 1e-15);
0279 
0280   /// Define the track (global) position and direction
0281   Vector3 globalPosition{0, 2, 2};
0282 
0283   // Test the derivative of bound track parameters local position w.r.t.
0284   // position in local 3D Cartesian coordinates
0285   const auto& loc3DToLocBound =
0286       cylinderSurfaceObject->localCartesianToBoundLocalDerivative(
0287           testContext, globalPosition);
0288   // Check if the result is as expected
0289   ActsMatrix<2, 3> expLoc3DToLocBound = ActsMatrix<2, 3>::Zero();
0290   expLoc3DToLocBound << -1, 0, 0, 0, 0, 1;
0291   CHECK_CLOSE_ABS(loc3DToLocBound, expLoc3DToLocBound, 1e-10);
0292 }
0293 
0294 BOOST_AUTO_TEST_CASE(CylinderSurfaceBinningPosition) {
0295   using namespace Acts::UnitLiterals;
0296   Vector3 s{5_mm, 7_mm, 10_cm};
0297   Transform3 trf;
0298   trf = Translation3(s) * AngleAxis3{0.5, Vector3::UnitZ()};
0299 
0300   double r = 300;
0301   double halfZ = 330;
0302   double averagePhi = 0.1;
0303 
0304   auto bounds =
0305       std::make_shared<CylinderBounds>(r, halfZ, M_PI / 8, averagePhi);
0306   auto cylinder = Acts::Surface::makeShared<CylinderSurface>(trf, bounds);
0307 
0308   Vector3 exp = Vector3{r * std::cos(averagePhi), r * std::sin(averagePhi), 0};
0309   exp = trf * exp;
0310 
0311   Vector3 bp = cylinder->binningPosition(testContext, binR);
0312   CHECK_CLOSE_ABS(bp, exp, 1e-10);
0313   CHECK_CLOSE_ABS(cylinder->binningPositionValue(testContext, binR),
0314                   VectorHelpers::perp(exp), 1e-10);
0315 
0316   bp = cylinder->binningPosition(testContext, binRPhi);
0317   CHECK_CLOSE_ABS(bp, exp, 1e-10);
0318   CHECK_CLOSE_ABS(cylinder->binningPositionValue(testContext, binRPhi),
0319                   VectorHelpers::phi(exp) * VectorHelpers::perp(exp), 1e-10);
0320 
0321   for (auto b : {binX, binY, binZ, binEta, binH, binMag}) {
0322     BOOST_TEST_CONTEXT("binValue: " << b) {
0323       BOOST_CHECK_EQUAL(cylinder->binningPosition(testContext, b),
0324                         cylinder->center(testContext));
0325     }
0326   }
0327 }
0328 
0329 BOOST_AUTO_TEST_SUITE_END()
0330 
0331 }  // namespace Acts::Test