Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-17 08:23:53

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/data/test_case.hpp>
0010 #include <boost/test/unit_test.hpp>
0011 
0012 #include "Acts/Definitions/Algebra.hpp"
0013 #include "Acts/Definitions/Common.hpp"
0014 #include "Acts/Definitions/TrackParametrization.hpp"
0015 #include "Acts/Definitions/Units.hpp"
0016 #include "Acts/EventData/BoundTrackParameters.hpp"
0017 #include "Acts/EventData/ParticleHypothesis.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/StrawSurface.hpp"
0024 #include "Acts/Surfaces/Surface.hpp"
0025 #include "Acts/Utilities/Result.hpp"
0026 #include "Acts/Utilities/UnitVectors.hpp"
0027 #include "Acts/Utilities/detail/periodic.hpp"
0028 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0029 
0030 #include <cmath>
0031 #include <limits>
0032 #include <memory>
0033 #include <numbers>
0034 #include <optional>
0035 
0036 #include "TrackParametersDatasets.hpp"
0037 
0038 namespace {
0039 
0040 namespace bdata = boost::unit_test::data;
0041 using namespace Acts;
0042 using namespace Acts::UnitLiterals;
0043 
0044 constexpr auto eps = 8 * std::numeric_limits<double>::epsilon();
0045 const auto geoCtx = GeometryContext::dangerouslyDefaultConstruct();
0046 const BoundMatrix cov = BoundMatrix::Identity();
0047 
0048 void checkParameters(const BoundTrackParameters& params, double l0, double l1,
0049                      double time, double phi, double theta, double p, double q,
0050                      const Vector3& pos, const Vector3& unitDir) {
0051   const auto particleHypothesis = ParticleHypothesis::pionLike(std::abs(q));
0052 
0053   const auto qOverP = particleHypothesis.qOverP(p, q);
0054   const auto pos4 = VectorHelpers::makeVector4(pos, time);
0055 
0056   // native values
0057   CHECK_CLOSE_OR_SMALL(params.template get<eBoundLoc0>(), l0, eps, eps);
0058   CHECK_CLOSE_OR_SMALL(params.template get<eBoundLoc1>(), l1, eps, eps);
0059   CHECK_CLOSE_OR_SMALL(params.template get<eBoundTime>(), time, eps, eps);
0060   CHECK_CLOSE_OR_SMALL(detail::radian_sym(params.template get<eBoundPhi>()),
0061                        detail::radian_sym(phi), eps, eps);
0062   CHECK_CLOSE_OR_SMALL(params.template get<eBoundTheta>(), theta, eps, eps);
0063   CHECK_CLOSE_OR_SMALL(params.template get<eBoundQOverP>(), qOverP, eps, eps);
0064   // convenience accessors
0065   BOOST_CHECK_EQUAL(params.charge(), q);
0066   CHECK_CLOSE_OR_SMALL(params.fourPosition(geoCtx), pos4, eps, eps);
0067   CHECK_CLOSE_OR_SMALL(params.position(geoCtx), pos, eps, eps);
0068   CHECK_CLOSE_OR_SMALL(params.time(), time, eps, eps);
0069   CHECK_CLOSE_OR_SMALL(params.direction(), unitDir, eps, eps);
0070   if (q != 0) {
0071     CHECK_CLOSE_OR_SMALL(params.absoluteMomentum(), p, eps, eps);
0072     CHECK_CLOSE_OR_SMALL(params.transverseMomentum(), p * std::sin(theta), eps,
0073                          eps);
0074     CHECK_CLOSE_OR_SMALL(params.momentum(), p * unitDir, eps, eps);
0075   }
0076 
0077   // reflection
0078   BoundTrackParameters reflectedParams = params;
0079   reflectedParams.reflectInPlace();
0080   CHECK_CLOSE_OR_SMALL(params.reflect().parameters(),
0081                        reflectedParams.parameters(), eps, eps);
0082   CHECK_CLOSE_OR_SMALL(reflectedParams.reflect().parameters(),
0083                        params.parameters(), eps, eps);
0084 }
0085 
0086 void runTest(const std::shared_ptr<const Surface>& surface, double l0,
0087              double l1, double time, double phi, double theta, double p) {
0088   // phi is ill-defined in forward/backward tracks
0089   phi = ((0 < theta) && (theta < std::numbers::pi)) ? phi : 0.;
0090 
0091   // global direction for reference
0092   const Vector3 dir = makeDirectionFromPhiTheta(phi, theta);
0093   // convert local-to-global for reference
0094   const Vector2 loc(l0, l1);
0095   const Vector3 pos = surface->localToGlobal(geoCtx, loc, dir);
0096   // global four-position as input
0097   Vector4 pos4;
0098   pos4.segment<3>(ePos0) = pos;
0099   pos4[eTime] = time;
0100 
0101   // neutral parameters from local vector
0102   {
0103     BoundVector vector = BoundVector::Zero();
0104     vector[eBoundLoc0] = l0;
0105     vector[eBoundLoc1] = l1;
0106     vector[eBoundTime] = time;
0107     vector[eBoundPhi] = phi;
0108     vector[eBoundTheta] = theta;
0109     vector[eBoundQOverP] = 0;
0110     BoundTrackParameters params(surface, vector, std::nullopt,
0111                                 ParticleHypothesis::pion0());
0112     checkParameters(params, l0, l1, time, phi, theta, p, 0_e, pos, dir);
0113     BOOST_CHECK(!params.covariance());
0114 
0115     // reassign w/ covariance
0116     params =
0117         BoundTrackParameters(surface, vector, cov, ParticleHypothesis::pion0());
0118     checkParameters(params, l0, l1, time, phi, theta, p, 0_e, pos, dir);
0119     BOOST_CHECK(params.covariance());
0120     BOOST_CHECK_EQUAL(params.covariance().value(), cov);
0121   }
0122   // negative charged parameters from local vector
0123   {
0124     BoundVector vector = BoundVector::Zero();
0125     vector[eBoundLoc0] = l0;
0126     vector[eBoundLoc1] = l1;
0127     vector[eBoundTime] = time;
0128     vector[eBoundPhi] = phi;
0129     vector[eBoundTheta] = theta;
0130     vector[eBoundQOverP] = -1_e / p;
0131     BoundTrackParameters params(surface, vector, std::nullopt,
0132                                 ParticleHypothesis::pion());
0133     checkParameters(params, l0, l1, time, phi, theta, p, -1_e, pos, dir);
0134     BOOST_CHECK(!params.covariance());
0135 
0136     // reassign w/ covariance
0137     params =
0138         BoundTrackParameters(surface, vector, cov, ParticleHypothesis::pion());
0139     checkParameters(params, l0, l1, time, phi, theta, p, -1_e, pos, dir);
0140     BOOST_CHECK(params.covariance());
0141     BOOST_CHECK_EQUAL(params.covariance().value(), cov);
0142   }
0143   // positive charged parameters from local vector
0144   {
0145     BoundVector vector = BoundVector::Zero();
0146     vector[eBoundLoc0] = l0;
0147     vector[eBoundLoc1] = l1;
0148     vector[eBoundTime] = time;
0149     vector[eBoundPhi] = phi;
0150     vector[eBoundTheta] = theta;
0151     vector[eBoundQOverP] = 1_e / p;
0152     BoundTrackParameters params(surface, vector, std::nullopt,
0153                                 ParticleHypothesis::pion());
0154     checkParameters(params, l0, l1, time, phi, theta, p, 1_e, pos, dir);
0155     BOOST_CHECK(!params.covariance());
0156 
0157     // reassign w/ covariance
0158     params =
0159         BoundTrackParameters(surface, vector, cov, ParticleHypothesis::pion());
0160     checkParameters(params, l0, l1, time, phi, theta, p, 1_e, pos, dir);
0161     BOOST_CHECK(params.covariance());
0162     BOOST_CHECK_EQUAL(params.covariance().value(), cov);
0163   }
0164   // double-negative charged any parameters from local vector
0165   {
0166     BoundVector vector = BoundVector::Zero();
0167     vector[eBoundLoc0] = l0;
0168     vector[eBoundLoc1] = l1;
0169     vector[eBoundTime] = time;
0170     vector[eBoundPhi] = phi;
0171     vector[eBoundTheta] = theta;
0172     vector[eBoundQOverP] = -2_e / p;
0173     BoundTrackParameters params(surface, vector, std::nullopt,
0174                                 ParticleHypothesis::pionLike(2_e));
0175     checkParameters(params, l0, l1, time, phi, theta, p, -2_e, pos, dir);
0176     BOOST_CHECK(!params.covariance());
0177 
0178     // reassign w/ covariance
0179     params = BoundTrackParameters(surface, vector, cov,
0180                                   ParticleHypothesis::pionLike(2_e));
0181     checkParameters(params, l0, l1, time, phi, theta, p, -2_e, pos, dir);
0182     BOOST_CHECK(params.covariance());
0183     BOOST_CHECK_EQUAL(params.covariance().value(), cov);
0184   }
0185   // neutral parameters from global information
0186   {
0187     auto params =
0188         BoundTrackParameters::create(geoCtx, surface, pos4, dir, 0,
0189                                      std::nullopt, ParticleHypothesis::pion0())
0190             .value();
0191     checkParameters(params, l0, l1, time, phi, theta, p, 0_e, pos, dir);
0192     BOOST_CHECK(!params.covariance());
0193   }
0194   // negative charged parameters from global information
0195   {
0196     auto params =
0197         BoundTrackParameters::create(geoCtx, surface, pos4, dir, -1_e / p,
0198                                      std::nullopt, ParticleHypothesis::pion())
0199             .value();
0200     checkParameters(params, l0, l1, time, phi, theta, p, -1_e, pos, dir);
0201     BOOST_CHECK(!params.covariance());
0202   }
0203   // positive charged parameters from global information
0204   {
0205     auto params =
0206         BoundTrackParameters::create(geoCtx, surface, pos4, dir, 1_e / p,
0207                                      std::nullopt, ParticleHypothesis::pion())
0208             .value();
0209     checkParameters(params, l0, l1, time, phi, theta, p, 1_e, pos, dir);
0210     BOOST_CHECK(!params.covariance());
0211   }
0212   // neutral any parameters from global information
0213   {
0214     auto params =
0215         BoundTrackParameters::create(geoCtx, surface, pos4, dir, 0,
0216                                      std::nullopt, ParticleHypothesis::pion0())
0217             .value();
0218     checkParameters(params, l0, l1, time, phi, theta, p, 0_e, pos, dir);
0219     BOOST_CHECK(!params.covariance());
0220   }
0221   // double-negative any parameters from global information
0222   {
0223     auto params = BoundTrackParameters::create(
0224                       geoCtx, surface, pos4, dir, -2_e / p, std::nullopt,
0225                       ParticleHypothesis::pionLike(2_e))
0226                       .value();
0227     checkParameters(params, l0, l1, time, phi, theta, p, -2_e, pos, dir);
0228     BOOST_CHECK(!params.covariance());
0229   }
0230   // triple-positive any parameters from global information
0231   {
0232     auto params = BoundTrackParameters::create(
0233                       geoCtx, surface, pos4, dir, 3_e / p, std::nullopt,
0234                       ParticleHypothesis::pionLike(3_e))
0235                       .value();
0236     checkParameters(params, l0, l1, time, phi, theta, p, 3_e, pos, dir);
0237     BOOST_CHECK(!params.covariance());
0238   }
0239 }
0240 
0241 // different surfaces
0242 // parameters must be chosen such that all possible local positions (as defined
0243 // in the dataset's header) represent valid points on the surface.
0244 const auto cones = bdata::make({
0245     Surface::makeShared<ConeSurface>(Transform3::Identity(),
0246                                      0.5 /* opening angle */),
0247 });
0248 const auto cylinders = bdata::make({
0249     Surface::makeShared<CylinderSurface>(Transform3::Identity(),
0250                                          10.0 /* radius */, 100 /* half z */),
0251 });
0252 const auto discs = bdata::make({
0253     Surface::makeShared<DiscSurface>(Transform3::Identity(), 0 /* radius min */,
0254                                      100 /* radius max */),
0255 });
0256 const auto perigees = bdata::make({
0257     Surface::makeShared<PerigeeSurface>(Vector3(0, 0, -1.5)),
0258 });
0259 const auto planes = bdata::make({
0260     CurvilinearSurface(Vector3(1, 2, 3), Vector3::UnitX()).planeSurface(),
0261     CurvilinearSurface(Vector3(-2, -3, -4), Vector3::UnitY()).planeSurface(),
0262     CurvilinearSurface(Vector3(3, -4, 5), Vector3::UnitZ()).planeSurface(),
0263 });
0264 const auto straws = bdata::make({
0265     Surface::makeShared<StrawSurface>(Transform3::Identity(), 2.0 /* radius */,
0266                                       200.0 /* half z */),
0267 });
0268 
0269 }  // namespace
0270 
0271 namespace ActsTests {
0272 
0273 BOOST_AUTO_TEST_SUITE(EventDataSuite)
0274 
0275 BOOST_DATA_TEST_CASE(ConeSurface,
0276                      cones * posAngle * posPositiveNonzero * ts * phis *
0277                          thetas * ps,
0278                      surface, lphi, lz, time, phi, theta, p) {
0279   // TODO extend lz to zero after fixing the transform implementation
0280   // local parameter r*phi has limits that depend on the z position
0281   const auto r = lz * surface->bounds().tanAlpha();
0282   // local coordinates are singular at z = 0 -> normalize local r*phi
0283   runTest(surface, (0 < lz) ? (r * lphi) : 0.0, lz, time, phi, theta, p);
0284 }
0285 
0286 BOOST_DATA_TEST_CASE(CylinderSurface,
0287                      cylinders * posSymmetric * posSymmetric * ts * phis *
0288                          thetas * ps,
0289                      surface, lrphi, lz, time, phi, theta, p) {
0290   runTest(surface, lrphi, lz, time, phi, theta, p);
0291 }
0292 
0293 BOOST_DATA_TEST_CASE(DiscSurface,
0294                      discs * posPositive * posAngle * ts * phis * thetas * ps,
0295                      surface, lr, lphi, time, phi, theta, p) {
0296   // local coordinates are singular at r = 0 -> normalize local phi
0297   runTest(surface, lr, (0 < lr) ? lphi : 0.0, time, phi, theta, p);
0298 }
0299 
0300 BOOST_DATA_TEST_CASE(PerigeeSurface,
0301                      perigees * posSymmetric * posSymmetric * ts * phis *
0302                          thetasNoForwardBackward * ps,
0303                      surface, d0, z0, time, phi, theta, p) {
0304   // TODO extend theta to forward/back extreme cases fixing the transform
0305   runTest(surface, d0, z0, time, phi, theta, p);
0306 }
0307 
0308 BOOST_DATA_TEST_CASE(PlaneSurface,
0309                      planes * posSymmetric * posSymmetric * ts * phis * thetas *
0310                          ps,
0311                      surface, l0, l1, time, phi, theta, p) {
0312   runTest(surface, l0, l1, time, phi, theta, p);
0313 }
0314 
0315 BOOST_DATA_TEST_CASE(StrawSurface,
0316                      straws * posPositive * posSymmetric * ts * phis *
0317                          thetasNoForwardBackward * ps,
0318                      surface, lr, lz, time, phi, theta, p) {
0319   // TODO extend theta to forward/back extreme cases fixing the transform
0320   runTest(surface, lr, lz, time, phi, theta, p);
0321 }
0322 
0323 BOOST_AUTO_TEST_SUITE_END()
0324 
0325 }  // namespace ActsTests