File indexing completed on 2025-10-30 07:55:28
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/TrackParametrization.hpp"
0014 #include "Acts/Definitions/Units.hpp"
0015 #include "Acts/EventData/SourceLink.hpp"
0016 #include "Acts/EventData/TrackParameters.hpp"
0017 #include "Acts/EventData/detail/TestSourceLink.hpp"
0018 #include "Acts/Geometry/GeometryContext.hpp"
0019 #include "Acts/Geometry/GeometryIdentifier.hpp"
0020 #include "Acts/Geometry/TrackingGeometry.hpp"
0021 #include "Acts/MagneticField/ConstantBField.hpp"
0022 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0023 #include "Acts/Propagator/EigenStepper.hpp"
0024 #include "Acts/Propagator/Navigator.hpp"
0025 #include "Acts/Propagator/Propagator.hpp"
0026 #include "Acts/SpacePointFormation/SpacePointBuilder.hpp"
0027 #include "Acts/SpacePointFormation/SpacePointBuilderConfig.hpp"
0028 #include "Acts/SpacePointFormation/SpacePointBuilderOptions.hpp"
0029 #include "Acts/Surfaces/Surface.hpp"
0030 #include "ActsTests/CommonHelpers/CubicTrackingGeometry.hpp"
0031 #include "ActsTests/CommonHelpers/MeasurementsCreator.hpp"
0032 #include "ActsTests/CommonHelpers/TestSpacePoint.hpp"
0033
0034 #include <iostream>
0035 #include <iterator>
0036 #include <memory>
0037 #include <optional>
0038 #include <random>
0039 #include <utility>
0040 #include <vector>
0041
0042 namespace bdata = boost::unit_test::data;
0043
0044 using namespace Acts;
0045 using namespace Acts::UnitLiterals;
0046
0047 namespace ActsTests {
0048
0049 using TestSourceLink = detail::Test::TestSourceLink;
0050 using ConstantFieldStepper = EigenStepper<>;
0051 using ConstantFieldPropagator = Propagator<ConstantFieldStepper, Navigator>;
0052
0053
0054 BoundTrackParameters makeParameters(double phi, double theta, double p,
0055 double q) {
0056
0057 BoundVector stddev;
0058 stddev[eBoundLoc0] = 100_um;
0059 stddev[eBoundLoc1] = 100_um;
0060 stddev[eBoundTime] = 25_ns;
0061 stddev[eBoundPhi] = 2_degree;
0062 stddev[eBoundTheta] = 2_degree;
0063 stddev[eBoundQOverP] = 1 / 100_GeV;
0064 BoundSquareMatrix cov = stddev.cwiseProduct(stddev).asDiagonal();
0065
0066 Vector4 mPos4(-3_m, 0., 0., 0.);
0067 return BoundTrackParameters::createCurvilinear(
0068 mPos4, phi, theta, q / p, cov, ParticleHypothesis::pionLike(q));
0069 }
0070
0071 std::pair<Vector3, Vector3> stripEnds(
0072 const std::shared_ptr<const TrackingGeometry>& geo,
0073 const GeometryContext& gctx, const SourceLink& slink,
0074 const double stripFrac = 0.4) {
0075 auto testslink = slink.get<TestSourceLink>();
0076 const auto lpos = testslink.parameters;
0077
0078 Vector3 globalFakeMom(1, 1, 1);
0079 const auto geoId = testslink.m_geometryId;
0080 const Surface* surface = geo->findSurface(geoId);
0081
0082 const double stripLength = 40.;
0083 const double end1x = lpos[0] + stripLength * stripFrac;
0084 const double end1y = lpos[1];
0085 const double end2x = lpos[0] - stripLength * (1 - stripFrac);
0086 const double end2y = lpos[1];
0087 const Vector2 lpos1(end1x, end1y);
0088 const Vector2 lpos2(end2x, end2y);
0089
0090 auto gPos1 = surface->localToGlobal(gctx, lpos1, globalFakeMom);
0091 auto gPos2 = surface->localToGlobal(gctx, lpos2, globalFakeMom);
0092
0093 return {gPos1, gPos2};
0094 }
0095
0096
0097 GeometryContext tgContext = GeometryContext();
0098
0099 const GeometryContext geoCtx;
0100 const MagneticFieldContext magCtx;
0101
0102
0103 CubicTrackingGeometry geometryStore(geoCtx);
0104 const auto geometry = geometryStore();
0105
0106
0107 const MeasurementResolution resPixel = {MeasurementType::eLoc01,
0108 {25_um, 50_um}};
0109 const MeasurementResolution resStrip = {MeasurementType::eLoc01,
0110 {100_um, 100_um}};
0111 const MeasurementResolutionMap resolutions = {
0112 {GeometryIdentifier().withVolume(2), resPixel},
0113 {GeometryIdentifier().withVolume(3).withLayer(2), resStrip},
0114 {GeometryIdentifier().withVolume(3).withLayer(4), resStrip},
0115 {GeometryIdentifier().withVolume(3).withLayer(6), resStrip},
0116 {GeometryIdentifier().withVolume(3).withLayer(8), resStrip},
0117 };
0118
0119 std::default_random_engine rng(42);
0120
0121 BOOST_AUTO_TEST_SUITE(SpacePointFormationSuite)
0122
0123 BOOST_DATA_TEST_CASE(SpacePointBuilder_basic, bdata::xrange(1), index) {
0124 (void)index;
0125
0126 double phi = 5._degree;
0127 double theta = 95._degree;
0128 double p = 50._GeV;
0129 double q = 1;
0130
0131 Navigator navigator({
0132 geometry,
0133 true,
0134 true,
0135 false
0136 });
0137 auto field = std::make_shared<ConstantBField>(Vector3(0.0, 0.0, 2._T));
0138 ConstantFieldStepper stepper(std::move(field));
0139
0140 ConstantFieldPropagator propagator(std::move(stepper), std::move(navigator));
0141 auto start = makeParameters(phi, theta, p, q);
0142
0143 auto measurements =
0144 createMeasurements(propagator, geoCtx, magCtx, start, resolutions, rng);
0145
0146 const auto sourceLinks = measurements.sourceLinks;
0147
0148 std::vector<SourceLink> frontSourceLinks;
0149 std::vector<SourceLink> backSourceLinks;
0150 std::vector<SourceLink> singleHitSourceLinks;
0151
0152 std::vector<const Vector3*> frontStripEnds;
0153 std::vector<const Vector3*> backStripEnds;
0154
0155 for (auto& sl : sourceLinks) {
0156 const auto geoId = sl.m_geometryId;
0157 const auto volumeId = geoId.volume();
0158 if (volumeId == 2) {
0159 singleHitSourceLinks.emplace_back(SourceLink{sl});
0160 } else if (volumeId == 3) {
0161
0162 const auto layerId = geoId.layer();
0163
0164 if (layerId == 2 || layerId == 6) {
0165 frontSourceLinks.emplace_back(SourceLink{sl});
0166 } else if (layerId == 4 || layerId == 8) {
0167 backSourceLinks.emplace_back(SourceLink{sl});
0168 }
0169 }
0170 }
0171
0172 BOOST_CHECK_EQUAL(frontSourceLinks.size(), 2);
0173 BOOST_CHECK_EQUAL(backSourceLinks.size(), 2);
0174
0175 Vector3 vertex = Vector3(-3_m, 0., 0.);
0176
0177 auto spConstructor = [](const Vector3& pos, const std::optional<double>& t,
0178 const Vector2& cov, const std::optional<double>& covT,
0179 boost::container::static_vector<SourceLink, 2> slinks)
0180 -> TestSpacePoint {
0181 return TestSpacePoint(pos, t, cov[0], cov[1], covT, std::move(slinks));
0182 };
0183
0184 auto spBuilderConfig = SpacePointBuilderConfig();
0185 spBuilderConfig.trackingGeometry = geometry;
0186
0187 TestSourceLink::SurfaceAccessor surfaceAccessor{*geometry};
0188 spBuilderConfig.slSurfaceAccessor
0189 .connect<&TestSourceLink::SurfaceAccessor::operator()>(&surfaceAccessor);
0190
0191 auto spBuilder =
0192 SpacePointBuilder<TestSpacePoint>(spBuilderConfig, spConstructor);
0193
0194
0195 auto spBuilderConfig_perp = SpacePointBuilderConfig();
0196 spBuilderConfig_perp.trackingGeometry = geometry;
0197 spBuilderConfig_perp.slSurfaceAccessor
0198 .connect<&TestSourceLink::SurfaceAccessor::operator()>(&surfaceAccessor);
0199
0200 spBuilderConfig_perp.usePerpProj = true;
0201
0202 auto spBuilder_perp =
0203 SpacePointBuilder<TestSpacePoint>(spBuilderConfig_perp, spConstructor);
0204
0205 TestSpacePointContainer spacePoints;
0206 TestSpacePointContainer spacePoints_extra;
0207
0208 auto accessor = [](const SourceLink& slink) {
0209 auto testslink = slink.get<TestSourceLink>();
0210 BoundVector param;
0211 param.setZero();
0212 param[eBoundLoc0] = testslink.parameters[eBoundLoc0];
0213 param[eBoundLoc1] = testslink.parameters[eBoundLoc1];
0214
0215 BoundSquareMatrix cov = BoundSquareMatrix::Zero();
0216 cov.topLeftCorner<2, 2>() = testslink.covariance;
0217
0218 return std::make_pair(param, cov);
0219 };
0220
0221 for (auto& sl : singleHitSourceLinks) {
0222 std::vector<SourceLink> slinks;
0223 slinks.emplace_back(sl);
0224 SpacePointBuilderOptions spOpt;
0225 spOpt.vertex = vertex;
0226 spOpt.paramCovAccessor = accessor;
0227 spBuilder.buildSpacePoint(geoCtx, slinks, spOpt,
0228 std::back_inserter(spacePoints));
0229 }
0230 BOOST_CHECK_EQUAL(spacePoints.size(), 2);
0231 std::vector<std::pair<SourceLink, SourceLink>> slinkPairs;
0232
0233
0234
0235 StripPairOptions pairOpt;
0236 pairOpt.paramCovAccessor = accessor;
0237
0238 spBuilder.makeSourceLinkPairs(tgContext, frontSourceLinks, backSourceLinks,
0239 slinkPairs, pairOpt);
0240
0241 BOOST_CHECK_EQUAL(slinkPairs.size(), 2);
0242
0243 for (auto& slinkPair : slinkPairs) {
0244 const std::pair<Vector3, Vector3> end1 =
0245 stripEnds(geometry, geoCtx, slinkPair.first);
0246 const std::pair<Vector3, Vector3> end2 =
0247 stripEnds(geometry, geoCtx, slinkPair.second);
0248
0249 std::shared_ptr<const TestSpacePoint> spacePoint = nullptr;
0250
0251 auto strippair = std::make_pair(end1, end2);
0252 std::vector<SourceLink> slinks;
0253 slinks.emplace_back(slinkPair.first);
0254 slinks.emplace_back(slinkPair.second);
0255
0256 SpacePointBuilderOptions spOpt{strippair, accessor};
0257
0258
0259 spBuilder.buildSpacePoint(geoCtx, slinks, spOpt,
0260 std::back_inserter(spacePoints));
0261
0262
0263 spBuilder_perp.buildSpacePoint(geoCtx, slinks, spOpt,
0264 std::back_inserter(spacePoints));
0265
0266
0267 const std::pair<Vector3, Vector3> end3 =
0268 stripEnds(geometry, geoCtx, slinkPair.first, 1.01);
0269 const std::pair<Vector3, Vector3> end4 =
0270 stripEnds(geometry, geoCtx, slinkPair.second, 1.02);
0271
0272 const std::pair<Vector3, Vector3> end5 =
0273 stripEnds(geometry, geoCtx, slinkPair.first, -0.01);
0274 const std::pair<Vector3, Vector3> end6 =
0275 stripEnds(geometry, geoCtx, slinkPair.second, -0.02);
0276
0277 auto spBuilderConfig_badStrips = SpacePointBuilderConfig();
0278
0279 spBuilderConfig_badStrips.trackingGeometry = geometry;
0280 spBuilderConfig_badStrips.slSurfaceAccessor
0281 .connect<&TestSourceLink::SurfaceAccessor::operator()>(
0282 &surfaceAccessor);
0283
0284 auto spBuilder_badStrips = SpacePointBuilder<TestSpacePoint>(
0285 spBuilderConfig_badStrips, spConstructor);
0286
0287 SpacePointBuilderOptions spOpt_badStrips1{std::make_pair(end3, end4),
0288 accessor};
0289 spOpt_badStrips1.vertex = vertex;
0290 spOpt_badStrips1.stripLengthTolerance = 0.0001;
0291 spOpt_badStrips1.stripLengthGapTolerance = 50.;
0292 spBuilder_badStrips.buildSpacePoint(geoCtx, slinks, spOpt_badStrips1,
0293 std::back_inserter(spacePoints_extra));
0294
0295 SpacePointBuilderOptions spOpt_badStrips2{std::make_pair(end5, end6),
0296 accessor};
0297 spOpt_badStrips2.vertex = vertex;
0298 spOpt_badStrips2.stripLengthTolerance = 0.0001;
0299 spOpt_badStrips2.stripLengthGapTolerance = 50.;
0300 spBuilder_badStrips.buildSpacePoint(geoCtx, slinks, spOpt_badStrips2,
0301 std::back_inserter(spacePoints_extra));
0302 }
0303
0304 for (auto& sp : spacePoints) {
0305 std::cout << "space point (" << sp.x() << " " << sp.y() << " " << sp.z()
0306 << ") var (r,z): " << sp.varianceR() << " " << sp.varianceZ()
0307 << std::endl;
0308 }
0309 std::cout << "space points produced with bad strips:" << std::endl;
0310 for (auto& sp : spacePoints_extra) {
0311 std::cout << "space point (" << sp.x() << " " << sp.y() << " " << sp.z()
0312 << ") var (r,z): " << sp.varianceR() << " " << sp.varianceZ()
0313 << std::endl;
0314 }
0315
0316 BOOST_CHECK_EQUAL(spacePoints.size(), 6);
0317 }
0318
0319 BOOST_AUTO_TEST_SUITE_END()
0320
0321 }