File indexing completed on 2025-08-05 08:10:24
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Direction.hpp"
0012 #include "Acts/Definitions/Units.hpp"
0013 #include "Acts/EventData/TrackParameters.hpp"
0014 #include "Acts/Geometry/GeometryContext.hpp"
0015 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0016 #include "Acts/Surfaces/CylinderSurface.hpp"
0017 #include "Acts/Surfaces/DiscSurface.hpp"
0018 #include "Acts/Surfaces/PlaneSurface.hpp"
0019 #include "Acts/Surfaces/StrawSurface.hpp"
0020 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0021 #include "Acts/Utilities/UnitVectors.hpp"
0022 #include "Acts/Utilities/detail/periodic.hpp"
0023
0024 #include <utility>
0025
0026
0027
0028
0029 inline Acts::CurvilinearTrackParameters makeParametersCurvilinear(
0030 double phi, double theta, double absMom, double charge) {
0031 using namespace Acts;
0032 using namespace Acts::UnitLiterals;
0033
0034
0035
0036 if (!((0 < theta) && (theta < M_PI))) {
0037 phi = 0;
0038 }
0039
0040 Vector4 pos4 = Vector4::Zero();
0041 auto particleHypothesis = ParticleHypothesis::pionLike(std::abs(charge));
0042 return CurvilinearTrackParameters(pos4, phi, theta,
0043 particleHypothesis.qOverP(absMom, charge),
0044 std::nullopt, particleHypothesis);
0045 }
0046
0047
0048 inline Acts::CurvilinearTrackParameters makeParametersCurvilinearWithCovariance(
0049 double phi, double theta, double absMom, double charge) {
0050 using namespace Acts;
0051 using namespace Acts::UnitLiterals;
0052
0053
0054
0055 if (!((0 < theta) && (theta < M_PI))) {
0056 phi = 0;
0057 }
0058
0059 BoundVector stddev = BoundVector::Zero();
0060
0061 stddev[eBoundLoc0] = 15_um;
0062 stddev[eBoundLoc1] = 80_um;
0063 stddev[eBoundTime] = 25_ns;
0064 stddev[eBoundPhi] = 1_degree;
0065 stddev[eBoundTheta] = 1.5_degree;
0066 stddev[eBoundQOverP] = 1_e / 10_GeV;
0067 BoundSquareMatrix corr = BoundSquareMatrix::Identity();
0068 corr(eBoundLoc0, eBoundLoc1) = corr(eBoundLoc1, eBoundLoc0) = 0.125;
0069 corr(eBoundLoc0, eBoundPhi) = corr(eBoundPhi, eBoundLoc0) = 0.25;
0070 corr(eBoundLoc1, eBoundTheta) = corr(eBoundTheta, eBoundLoc1) = -0.25;
0071 corr(eBoundTime, eBoundQOverP) = corr(eBoundQOverP, eBoundTime) = 0.125;
0072 corr(eBoundPhi, eBoundTheta) = corr(eBoundTheta, eBoundPhi) = -0.25;
0073 corr(eBoundPhi, eBoundQOverP) = corr(eBoundPhi, eBoundQOverP) = -0.125;
0074 corr(eBoundTheta, eBoundQOverP) = corr(eBoundTheta, eBoundQOverP) = 0.5;
0075 BoundSquareMatrix cov = stddev.asDiagonal() * corr * stddev.asDiagonal();
0076
0077 Vector4 pos4 = Vector4::Zero();
0078 auto particleHypothesis = ParticleHypothesis::pionLike(std::abs(charge));
0079 return CurvilinearTrackParameters(pos4, phi, theta,
0080 particleHypothesis.qOverP(absMom, charge),
0081 cov, particleHypothesis);
0082 }
0083
0084
0085 inline Acts::CurvilinearTrackParameters makeParametersCurvilinearNeutral(
0086 double phi, double theta, double absMom) {
0087 using namespace Acts;
0088 using namespace Acts::UnitLiterals;
0089
0090
0091
0092 if (!((0 < theta) && (theta < M_PI))) {
0093 phi = 0;
0094 }
0095
0096 Vector4 pos4 = Vector4::Zero();
0097 return CurvilinearTrackParameters(pos4, phi, theta, 1 / absMom, std::nullopt,
0098 ParticleHypothesis::pion0());
0099 }
0100
0101
0102
0103
0104
0105
0106 inline void checkParametersConsistency(const Acts::BoundTrackParameters& cmp,
0107 const Acts::BoundTrackParameters& ref,
0108 const Acts::GeometryContext& geoCtx,
0109 double epsPos, double epsDir,
0110 double epsMom) {
0111 using namespace Acts;
0112
0113
0114 CHECK_CLOSE_ABS(cmp.template get<eBoundLoc0>(),
0115 ref.template get<eBoundLoc0>(), epsPos);
0116 CHECK_CLOSE_ABS(cmp.template get<eBoundLoc1>(),
0117 ref.template get<eBoundLoc1>(), epsPos);
0118 CHECK_CLOSE_ABS(cmp.template get<eBoundTime>(),
0119 ref.template get<eBoundTime>(), epsPos);
0120
0121 CHECK_SMALL(detail::radian_sym(cmp.template get<eBoundPhi>() -
0122 ref.template get<eBoundPhi>()),
0123 epsDir);
0124 CHECK_CLOSE_ABS(cmp.template get<eBoundTheta>(),
0125 ref.template get<eBoundTheta>(), epsDir);
0126 CHECK_CLOSE_ABS(cmp.template get<eBoundQOverP>(),
0127 ref.template get<eBoundQOverP>(), epsMom);
0128
0129 CHECK_CLOSE_ABS(cmp.position(geoCtx), ref.position(geoCtx), epsPos);
0130 CHECK_CLOSE_ABS(cmp.time(), ref.time(), epsPos);
0131 CHECK_CLOSE_ABS(cmp.direction(), ref.direction(), epsDir);
0132 CHECK_CLOSE_ABS(cmp.absoluteMomentum(), ref.absoluteMomentum(), epsMom);
0133
0134 BOOST_CHECK_EQUAL(cmp.charge(), ref.charge());
0135 }
0136
0137
0138
0139
0140 inline void checkCovarianceConsistency(const Acts::BoundTrackParameters& cmp,
0141 const Acts::BoundTrackParameters& ref,
0142 double relativeTolerance) {
0143
0144 if (cmp.covariance().has_value()) {
0145
0146 BOOST_CHECK(ref.covariance().has_value());
0147 }
0148 if (ref.covariance().has_value()) {
0149
0150 BOOST_CHECK(cmp.covariance().has_value());
0151 }
0152 if (cmp.covariance().has_value() && ref.covariance().has_value()) {
0153 CHECK_CLOSE_COVARIANCE(cmp.covariance().value(), ref.covariance().value(),
0154 relativeTolerance);
0155 }
0156 }
0157
0158
0159
0160
0161 inline Acts::Transform3 makeCurvilinearTransform(
0162 const Acts::BoundTrackParameters& params,
0163 const Acts::GeometryContext& geoCtx) {
0164 Acts::Vector3 unitW = params.direction();
0165 auto [unitU, unitV] = Acts::makeCurvilinearUnitVectors(unitW);
0166
0167 Acts::RotationMatrix3 rotation = Acts::RotationMatrix3::Zero();
0168 rotation.col(0) = unitU;
0169 rotation.col(1) = unitV;
0170 rotation.col(2) = unitW;
0171 Acts::Translation3 offset(params.position(geoCtx));
0172 Acts::Transform3 toGlobal = offset * rotation;
0173
0174 return toGlobal;
0175 }
0176
0177
0178 struct ZCylinderSurfaceBuilder {
0179 std::shared_ptr<Acts::CylinderSurface> operator()(
0180 const Acts::BoundTrackParameters& params,
0181 const Acts::GeometryContext& geoCtx) {
0182 auto radius = params.position(geoCtx).template head<2>().norm();
0183 auto halfz = std::numeric_limits<double>::max();
0184 return Acts::Surface::makeShared<Acts::CylinderSurface>(
0185 Acts::Transform3::Identity(), radius, halfz);
0186 }
0187 };
0188
0189
0190 struct DiscSurfaceBuilder {
0191 std::shared_ptr<Acts::DiscSurface> operator()(
0192 const Acts::BoundTrackParameters& params,
0193 const Acts::GeometryContext& geoCtx) {
0194 using namespace Acts;
0195 using namespace Acts::UnitLiterals;
0196
0197 auto cl = makeCurvilinearTransform(params, geoCtx);
0198
0199
0200
0201
0202 Acts::Vector3 localOffset = Acts::Vector3::Zero();
0203 localOffset[Acts::ePos0] = 1_cm;
0204 localOffset[Acts::ePos1] = -1_cm;
0205 Acts::Vector3 globalOriginDelta = cl.linear() * localOffset;
0206 cl.pretranslate(globalOriginDelta);
0207
0208 return Acts::Surface::makeShared<Acts::DiscSurface>(cl);
0209 }
0210 };
0211
0212
0213 struct PlaneSurfaceBuilder {
0214 std::shared_ptr<Acts::PlaneSurface> operator()(
0215 const Acts::BoundTrackParameters& params,
0216 const Acts::GeometryContext& geoCtx) {
0217 return Acts::Surface::makeShared<Acts::PlaneSurface>(
0218 makeCurvilinearTransform(params, geoCtx));
0219 }
0220 };
0221
0222
0223 struct ZStrawSurfaceBuilder {
0224 std::shared_ptr<Acts::StrawSurface> operator()(
0225 const Acts::BoundTrackParameters& params,
0226 const Acts::GeometryContext& geoCtx) {
0227 return Acts::Surface::makeShared<Acts::StrawSurface>(
0228 Acts::Transform3(Acts::Translation3(params.position(geoCtx))));
0229 }
0230 };
0231
0232
0233
0234
0235
0236
0237 template <typename propagator_t, template <typename, typename>
0238 class options_t = Acts::PropagatorOptions>
0239 inline std::pair<Acts::CurvilinearTrackParameters, double> transportFreely(
0240 const propagator_t& propagator, const Acts::GeometryContext& geoCtx,
0241 const Acts::MagneticFieldContext& magCtx,
0242 const Acts::CurvilinearTrackParameters& initialParams, double pathLength) {
0243 using namespace Acts::UnitLiterals;
0244
0245 using Actions = Acts::ActionList<>;
0246 using Aborts = Acts::AbortList<>;
0247
0248
0249 options_t<Actions, Aborts> options(geoCtx, magCtx);
0250 options.direction = Acts::Direction::fromScalar(pathLength);
0251 options.pathLimit = pathLength;
0252 options.surfaceTolerance = 1_nm;
0253 options.stepTolerance = 1_nm;
0254
0255 auto result = propagator.propagate(initialParams, options);
0256 BOOST_CHECK(result.ok());
0257 BOOST_CHECK(result.value().endParameters);
0258
0259 return {*result.value().endParameters, result.value().pathLength};
0260 }
0261
0262
0263 template <typename propagator_t, template <typename, typename>
0264 class options_t = Acts::PropagatorOptions>
0265 inline std::pair<Acts::BoundTrackParameters, double> transportToSurface(
0266 const propagator_t& propagator, const Acts::GeometryContext& geoCtx,
0267 const Acts::MagneticFieldContext& magCtx,
0268 const Acts::CurvilinearTrackParameters& initialParams,
0269 const Acts::Surface& targetSurface, double pathLimit) {
0270 using namespace Acts::UnitLiterals;
0271
0272 using Actions = Acts::ActionList<>;
0273 using Aborts = Acts::AbortList<>;
0274
0275
0276 options_t<Actions, Aborts> options(geoCtx, magCtx);
0277 options.direction = Acts::Direction::Forward;
0278 options.pathLimit = pathLimit;
0279 options.surfaceTolerance = 1_nm;
0280 options.stepTolerance = 1_nm;
0281
0282 auto result = propagator.propagate(initialParams, targetSurface, options);
0283 BOOST_CHECK(result.ok());
0284 BOOST_CHECK(result.value().endParameters);
0285
0286 return {*result.value().endParameters, result.value().pathLength};
0287 }
0288
0289
0290
0291
0292
0293
0294 template <typename propagator_t, template <typename, typename>
0295 class options_t = Acts::PropagatorOptions>
0296 inline void runForwardBackwardTest(
0297 const propagator_t& propagator, const Acts::GeometryContext& geoCtx,
0298 const Acts::MagneticFieldContext& magCtx,
0299 const Acts::CurvilinearTrackParameters& initialParams, double pathLength,
0300 double epsPos, double epsDir, double epsMom) {
0301
0302 auto [fwdParams, fwdPathLength] = transportFreely<propagator_t, options_t>(
0303 propagator, geoCtx, magCtx, initialParams, pathLength);
0304 CHECK_CLOSE_ABS(fwdPathLength, pathLength, epsPos);
0305
0306 auto [bwdParams, bwdPathLength] = transportFreely<propagator_t, options_t>(
0307 propagator, geoCtx, magCtx, fwdParams, -pathLength);
0308 CHECK_CLOSE_ABS(bwdPathLength, -pathLength, epsPos);
0309
0310 checkParametersConsistency(initialParams, bwdParams, geoCtx, epsPos, epsDir,
0311 epsMom);
0312 }
0313
0314
0315
0316
0317
0318 template <typename propagator_t, typename surface_builder_t,
0319 template <typename, typename>
0320 class options_t = Acts::PropagatorOptions>
0321 inline void runToSurfaceTest(
0322 const propagator_t& propagator, const Acts::GeometryContext& geoCtx,
0323 const Acts::MagneticFieldContext& magCtx,
0324 const Acts::CurvilinearTrackParameters& initialParams, double pathLength,
0325 surface_builder_t&& buildTargetSurface, double epsPos, double epsDir,
0326 double epsMom) {
0327
0328 auto [freeParams, freePathLength] = transportFreely<propagator_t, options_t>(
0329 propagator, geoCtx, magCtx, initialParams, pathLength);
0330 CHECK_CLOSE_ABS(freePathLength, pathLength, epsPos);
0331
0332 auto surface = buildTargetSurface(freeParams, geoCtx);
0333 BOOST_CHECK(surface);
0334
0335
0336
0337 auto [surfParams, surfPathLength] =
0338 transportToSurface<propagator_t, options_t>(propagator, geoCtx, magCtx,
0339 initialParams, *surface,
0340 1.5 * pathLength);
0341 CHECK_CLOSE_ABS(surfPathLength, pathLength, epsPos);
0342
0343
0344 CHECK_CLOSE_ABS(surfParams.position(geoCtx), freeParams.position(geoCtx),
0345 epsPos);
0346 CHECK_CLOSE_ABS(surfParams.time(), freeParams.time(), epsPos);
0347 CHECK_CLOSE_ABS(surfParams.direction(), freeParams.direction(), epsDir);
0348 CHECK_CLOSE_ABS(surfParams.absoluteMomentum(), freeParams.absoluteMomentum(),
0349 epsMom);
0350 CHECK_CLOSE_ABS(surfPathLength, freePathLength, epsPos);
0351 }
0352
0353
0354
0355
0356
0357 template <typename cmp_propagator_t, typename ref_propagator_t,
0358 template <typename, typename>
0359 class options_t = Acts::PropagatorOptions>
0360 inline void runForwardComparisonTest(
0361 const cmp_propagator_t& cmpPropagator,
0362 const ref_propagator_t& refPropagator, const Acts::GeometryContext& geoCtx,
0363 const Acts::MagneticFieldContext& magCtx,
0364 const Acts::CurvilinearTrackParameters& initialParams, double pathLength,
0365 double epsPos, double epsDir, double epsMom, double tolCov) {
0366
0367 auto [cmpParams, cmpPath] = transportFreely<cmp_propagator_t, options_t>(
0368 cmpPropagator, geoCtx, magCtx, initialParams, pathLength);
0369 auto [refParams, refPath] = transportFreely<ref_propagator_t, options_t>(
0370 refPropagator, geoCtx, magCtx, initialParams, pathLength);
0371
0372 checkParametersConsistency(cmpParams, refParams, geoCtx, epsPos, epsDir,
0373 epsMom);
0374 checkCovarianceConsistency(cmpParams, refParams, tolCov);
0375 CHECK_CLOSE_ABS(cmpPath, pathLength, epsPos);
0376 CHECK_CLOSE_ABS(refPath, pathLength, epsPos);
0377 CHECK_CLOSE_ABS(cmpPath, refPath, epsPos);
0378 }
0379
0380
0381
0382
0383
0384 template <typename cmp_propagator_t, typename ref_propagator_t,
0385 typename surface_builder_t,
0386 template <typename, typename>
0387 class options_t = Acts::PropagatorOptions>
0388 inline void runToSurfaceComparisonTest(
0389 const cmp_propagator_t& cmpPropagator,
0390 const ref_propagator_t& refPropagator, const Acts::GeometryContext& geoCtx,
0391 const Acts::MagneticFieldContext& magCtx,
0392 const Acts::CurvilinearTrackParameters& initialParams, double pathLength,
0393 surface_builder_t&& buildTargetSurface, double epsPos, double epsDir,
0394 double epsMom, double tolCov) {
0395
0396 auto [freeParams, freePathLength] =
0397 transportFreely<ref_propagator_t, options_t>(
0398 refPropagator, geoCtx, magCtx, initialParams, pathLength);
0399 CHECK_CLOSE_ABS(freePathLength, pathLength, epsPos);
0400
0401
0402 auto surface = buildTargetSurface(freeParams, geoCtx);
0403 BOOST_CHECK(surface);
0404
0405
0406
0407 auto [cmpParams, cmpPath] = transportToSurface<cmp_propagator_t, options_t>(
0408 cmpPropagator, geoCtx, magCtx, initialParams, *surface, 1.5 * pathLength);
0409 auto [refParams, refPath] = transportToSurface<ref_propagator_t, options_t>(
0410 refPropagator, geoCtx, magCtx, initialParams, *surface, 1.5 * pathLength);
0411
0412 checkParametersConsistency(cmpParams, refParams, geoCtx, epsPos, epsDir,
0413 epsMom);
0414 checkCovarianceConsistency(cmpParams, refParams, tolCov);
0415 CHECK_CLOSE_ABS(cmpPath, pathLength, epsPos);
0416 CHECK_CLOSE_ABS(refPath, pathLength, epsPos);
0417 CHECK_CLOSE_ABS(cmpPath, refPath, epsPos);
0418 }