Back to home page

sPhenix code displayed by LXR

 
 

    


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

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2020 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 // This file contains systematic tests to verify the local->global->local
0010 // transformation roundtrip for all available surfaces with a large range of
0011 // possible parameters.
0012 
0013 #include <boost/test/data/test_case.hpp>
0014 #include <boost/test/unit_test.hpp>
0015 
0016 #include "Acts/Definitions/Algebra.hpp"
0017 #include "Acts/Definitions/Common.hpp"
0018 #include "Acts/Geometry/GeometryContext.hpp"
0019 #include "Acts/Surfaces/ConeSurface.hpp"
0020 #include "Acts/Surfaces/CylinderSurface.hpp"
0021 #include "Acts/Surfaces/DiscSurface.hpp"
0022 #include "Acts/Surfaces/PerigeeSurface.hpp"
0023 #include "Acts/Surfaces/PlaneSurface.hpp"
0024 #include "Acts/Surfaces/StrawSurface.hpp"
0025 #include "Acts/Surfaces/Surface.hpp"
0026 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0027 #include "Acts/Utilities/Result.hpp"
0028 #include "Acts/Utilities/UnitVectors.hpp"
0029 
0030 #include <cmath>
0031 #include <limits>
0032 #include <memory>
0033 #include <ostream>
0034 #include <type_traits>
0035 #include <utility>
0036 #include <vector>
0037 
0038 namespace {
0039 
0040 namespace bdata = boost::unit_test::data;
0041 using namespace Acts;
0042 
0043 constexpr auto eps = 8 * std::numeric_limits<double>::epsilon();
0044 const GeometryContext geoCtx;
0045 
0046 void runTest(const Surface& surface, double l0, double l1, double phi,
0047              double theta) {
0048   const Vector3 dir = makeDirectionFromPhiTheta(phi, theta);
0049 
0050   // convert local-to-global
0051   Vector3 sentinel = Vector3::Random();
0052   Vector3 pos = surface.localToGlobal(geoCtx, Vector2(l0, l1), dir);
0053   BOOST_CHECK_MESSAGE(pos != sentinel, "Position was not changed");
0054   BOOST_CHECK_MESSAGE(
0055       std::isfinite(pos[0]),
0056       "Position " << pos.transpose() << " contains non-finite entries");
0057   BOOST_CHECK_MESSAGE(
0058       std::isfinite(pos[1]),
0059       "Position " << pos.transpose() << " contains non-finite entries");
0060   BOOST_CHECK_MESSAGE(
0061       std::isfinite(pos[2]),
0062       "Position " << pos.transpose() << " contains non-finite entries");
0063   BOOST_CHECK_MESSAGE(
0064       surface.isOnSurface(geoCtx, pos, dir),
0065       "Position " << pos.transpose() << " is not on the surface");
0066 
0067   // convert global-to-local
0068   auto lpResult = surface.globalToLocal(geoCtx, pos, dir);
0069   BOOST_CHECK(lpResult.ok());
0070   CHECK_CLOSE_OR_SMALL(lpResult.value()[ePos0], l0, eps, eps);
0071   CHECK_CLOSE_OR_SMALL(lpResult.value()[ePos1], l1, eps, eps);
0072 }
0073 
0074 // test datasets
0075 
0076 // local positions
0077 const auto posAngle = bdata::xrange(-M_PI, M_PI, 0.25);
0078 const auto posPositiveNonzero = bdata::xrange(0.25, 1.0, 0.25);
0079 const auto posPositive = bdata::make(0.0) + posPositiveNonzero;
0080 const auto posSymmetric = bdata::xrange(-1.0, 1.0, 0.25);
0081 // direction angles
0082 const auto phis = bdata::xrange(-M_PI, M_PI, M_PI_4);
0083 const auto thetasNoForwardBackward = bdata::xrange(M_PI_4, M_PI, M_PI_4);
0084 const auto thetas = bdata::make({0.0, M_PI}) + thetasNoForwardBackward;
0085 
0086 // different surfaces
0087 // parameters must be chosen such that all possible local positions (as defined
0088 // in the datasets above) represent valid points on the surface.
0089 const auto cones = bdata::make({
0090     Surface::makeShared<ConeSurface>(Transform3::Identity(),
0091                                      0.5 /* opening angle */),
0092 });
0093 const auto cylinders = bdata::make({
0094     Surface::makeShared<CylinderSurface>(Transform3::Identity(),
0095                                          10.0 /* radius */, 100 /* half z */),
0096 });
0097 const auto discs = bdata::make({
0098     Surface::makeShared<DiscSurface>(Transform3::Identity(), 0 /* radius min */,
0099                                      100 /* radius max */),
0100 });
0101 const auto perigees = bdata::make({
0102     Surface::makeShared<PerigeeSurface>(Vector3(0, 0, -1.5)),
0103 });
0104 const auto planes = bdata::make({
0105     Surface::makeShared<PlaneSurface>(Vector3(1, 2, 3), Vector3::UnitX()),
0106     Surface::makeShared<PlaneSurface>(Vector3(-2, -3, -4), Vector3::UnitY()),
0107     Surface::makeShared<PlaneSurface>(Vector3(3, -4, 5), Vector3::UnitZ()),
0108 });
0109 const auto straws = bdata::make({
0110     Surface::makeShared<StrawSurface>(Transform3::Identity(), 2.0 /* radius */,
0111                                       200.0 /* half z */),
0112 });
0113 
0114 }  // namespace
0115 
0116 BOOST_AUTO_TEST_SUITE(SurfaceLocalToGlobalRoundtrip)
0117 
0118 BOOST_DATA_TEST_CASE(ConeSurface,
0119                      cones* posAngle* posPositiveNonzero* phis* thetas, surface,
0120                      lphi, lz, phi, theta) {
0121   // TODO extend lz to zero after fixing the transform implementation
0122   // local parameter r*phi has limits that depend on the z position
0123   const auto r = lz * surface->bounds().tanAlpha();
0124   // local coordinates are singular at z = 0 -> normalize local phi
0125   runTest(*surface, (0 < lz) ? (r * lphi) : 0.0, lz, phi, theta);
0126 }
0127 
0128 BOOST_DATA_TEST_CASE(CylinderSurface,
0129                      cylinders* posSymmetric* posSymmetric* phis* thetas,
0130                      surface, lrphi, lz, phi, theta) {
0131   runTest(*surface, lrphi, lz, phi, theta);
0132 }
0133 
0134 BOOST_DATA_TEST_CASE(DiscSurface, discs* posPositive* posAngle* phis* thetas,
0135                      surface, lr, lphi, phi, theta) {
0136   // local coordinates are singular at r = 0 -> normalize local phi
0137   runTest(*surface, lr, (0 < lr) ? lphi : 0.0, phi, theta);
0138 }
0139 
0140 BOOST_DATA_TEST_CASE(
0141     PerigeeSurface,
0142     perigees* posSymmetric* posSymmetric* phis* thetasNoForwardBackward,
0143     surface, d0, z0, phi, theta) {
0144   // TODO extend theta to forward/back extreme cases fixing the transform
0145   runTest(*surface, d0, z0, phi, theta);
0146 }
0147 
0148 BOOST_DATA_TEST_CASE(PlaneSurface,
0149                      planes* posSymmetric* posSymmetric* phis* thetas, surface,
0150                      l0, l1, phi, theta) {
0151   runTest(*surface, l0, l1, phi, theta);
0152 }
0153 
0154 BOOST_DATA_TEST_CASE(
0155     StrawSurface,
0156     straws* posSymmetric* posSymmetric* phis* thetasNoForwardBackward, surface,
0157     lr, lz, phi, theta) {
0158   // TODO extend theta to forward/back extreme cases fixing the transform
0159   runTest(*surface, lr, lz, phi, theta);
0160 }
0161 
0162 BOOST_AUTO_TEST_SUITE_END()