File indexing completed on 2026-09-17 08:23:53
0001
0002
0003
0004
0005
0006
0007
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
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
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
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
0089 phi = ((0 < theta) && (theta < std::numbers::pi)) ? phi : 0.;
0090
0091
0092 const Vector3 dir = makeDirectionFromPhiTheta(phi, theta);
0093
0094 const Vector2 loc(l0, l1);
0095 const Vector3 pos = surface->localToGlobal(geoCtx, loc, dir);
0096
0097 Vector4 pos4;
0098 pos4.segment<3>(ePos0) = pos;
0099 pos4[eTime] = time;
0100
0101
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
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
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
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
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
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
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
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
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
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
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
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
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
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
0242
0243
0244 const auto cones = bdata::make({
0245 Surface::makeShared<ConeSurface>(Transform3::Identity(),
0246 0.5 ),
0247 });
0248 const auto cylinders = bdata::make({
0249 Surface::makeShared<CylinderSurface>(Transform3::Identity(),
0250 10.0 , 100 ),
0251 });
0252 const auto discs = bdata::make({
0253 Surface::makeShared<DiscSurface>(Transform3::Identity(), 0 ,
0254 100 ),
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 ,
0266 200.0 ),
0267 });
0268
0269 }
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
0280
0281 const auto r = lz * surface->bounds().tanAlpha();
0282
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
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
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
0320 runTest(surface, lr, lz, time, phi, theta, p);
0321 }
0322
0323 BOOST_AUTO_TEST_SUITE_END()
0324
0325 }