Warning, file /acts/Tests/UnitTests/Core/Vertexing/GridDensityVertexFinderTests.cpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Common.hpp"
0013 #include "Acts/Definitions/TrackParametrization.hpp"
0014 #include "Acts/Definitions/Units.hpp"
0015 #include "Acts/EventData/TrackParameters.hpp"
0016 #include "Acts/Geometry/GeometryContext.hpp"
0017 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0018 #include "Acts/Surfaces/PerigeeSurface.hpp"
0019 #include "Acts/Surfaces/Surface.hpp"
0020 #include "Acts/Utilities/Intersection.hpp"
0021 #include "Acts/Utilities/Result.hpp"
0022 #include "Acts/Utilities/UnitVectors.hpp"
0023 #include "Acts/Vertexing/AdaptiveGridDensityVertexFinder.hpp"
0024 #include "Acts/Vertexing/AdaptiveGridTrackDensity.hpp"
0025 #include "Acts/Vertexing/GaussianGridTrackDensity.hpp"
0026 #include "Acts/Vertexing/GridDensityVertexFinder.hpp"
0027 #include "Acts/Vertexing/IVertexFinder.hpp"
0028 #include "Acts/Vertexing/Vertex.hpp"
0029 #include "Acts/Vertexing/VertexingOptions.hpp"
0030 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0031
0032 #include <iostream>
0033 #include <memory>
0034 #include <numbers>
0035 #include <random>
0036 #include <system_error>
0037 #include <vector>
0038
0039 using namespace Acts;
0040 using namespace Acts::UnitLiterals;
0041 using Acts::VectorHelpers::makeVector4;
0042
0043 namespace ActsTests {
0044
0045 using Covariance = BoundSquareMatrix;
0046
0047
0048 GeometryContext geoContext = GeometryContext();
0049 MagneticFieldContext magFieldContext = MagneticFieldContext();
0050
0051 const double zVertexPos1 = 12.;
0052 const double zVertexPos2 = -3.;
0053
0054 std::normal_distribution<double> xdist(1_mm, 0.1_mm);
0055
0056 std::normal_distribution<double> ydist(-0.7_mm, 0.1_mm);
0057
0058 std::normal_distribution<double> z1dist(zVertexPos1 * 1_mm, 1_mm);
0059
0060 std::normal_distribution<double> z2dist(zVertexPos2 * 1_mm, 0.5_mm);
0061
0062 std::uniform_real_distribution<double> pTDist(0.1_GeV, 100_GeV);
0063
0064 std::uniform_real_distribution<double> phiDist(-std::numbers::pi,
0065 std::numbers::pi);
0066
0067 std::uniform_real_distribution<double> etaDist(-4., 4.);
0068
0069 BOOST_AUTO_TEST_SUITE(VertexingSuite)
0070
0071
0072
0073
0074 BOOST_AUTO_TEST_CASE(grid_density_vertex_finder_test) {
0075 bool debugMode = false;
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 const int mainGridSize = 3001;
0088 const int trkGridSize = 35;
0089
0090 Covariance covMat = Covariance::Identity();
0091
0092
0093 Vector3 pos0{0, 0, 0};
0094 std::shared_ptr<PerigeeSurface> perigeeSurface =
0095 Surface::makeShared<PerigeeSurface>(pos0);
0096
0097 VertexingOptions vertexingOptions(geoContext, magFieldContext);
0098
0099 using Finder1 = GridDensityVertexFinder;
0100 GaussianGridTrackDensity::Config gDensityConfig(100, mainGridSize,
0101 trkGridSize);
0102 GaussianGridTrackDensity gDensity(gDensityConfig);
0103 Finder1::Config cfg1(gDensity);
0104 cfg1.cacheGridStateForTrackRemoval = false;
0105 cfg1.extractParameters.connect<&InputTrack::extractParameters>();
0106 Finder1 finder1(cfg1);
0107 IVertexFinder::State state1 = finder1.makeState(magFieldContext);
0108
0109
0110 AdaptiveGridTrackDensity::Config adaptiveDensityConfig;
0111 adaptiveDensityConfig.spatialTrkGridSizeRange = {trkGridSize, trkGridSize};
0112 adaptiveDensityConfig.spatialBinExtent = 2. / 30.01 * 1_mm;
0113 AdaptiveGridTrackDensity adaptiveDensity(adaptiveDensityConfig);
0114
0115 using Finder2 = AdaptiveGridDensityVertexFinder;
0116 Finder2::Config cfg2(adaptiveDensity);
0117 cfg2.cacheGridStateForTrackRemoval = false;
0118 cfg2.extractParameters.connect<&InputTrack::extractParameters>();
0119 Finder2 finder2(cfg2);
0120 IVertexFinder::State state2 = finder2.makeState(magFieldContext);
0121
0122 int mySeed = 31415;
0123 std::mt19937 gen(mySeed);
0124 unsigned int nTracks = 200;
0125
0126 std::vector<BoundTrackParameters> trackVec;
0127 trackVec.reserve(nTracks);
0128
0129
0130 for (unsigned int i = 0; i < nTracks; i++) {
0131
0132 Vector3 pos(xdist(gen), ydist(gen), 0);
0133
0134
0135 double pt = pTDist(gen);
0136 double phi = phiDist(gen);
0137 double eta = etaDist(gen);
0138 double charge = std::copysign(1., etaDist(gen));
0139
0140
0141 Vector3 direction = makeDirectionFromPhiEta(phi, eta);
0142 Intersection3D intersection =
0143 perigeeSurface->intersect(geoContext, pos, direction).closest();
0144 pos = intersection.position();
0145
0146
0147
0148 pos[eZ] = ((i % 4) == 0) ? z2dist(gen) : z1dist(gen);
0149
0150 trackVec.push_back(BoundTrackParameters::create(
0151 geoContext, perigeeSurface, makeVector4(pos, 0),
0152 direction, charge / pt, covMat,
0153 ParticleHypothesis::pion())
0154 .value());
0155 }
0156
0157 std::vector<InputTrack> inputTracks;
0158 for (const auto& trk : trackVec) {
0159 inputTracks.emplace_back(&trk);
0160 }
0161
0162 auto res1 = finder1.find(inputTracks, vertexingOptions, state1);
0163 if (!res1.ok()) {
0164 std::cout << res1.error().message() << std::endl;
0165 }
0166
0167 auto res2 = finder2.find(inputTracks, vertexingOptions, state2);
0168 if (!res2.ok()) {
0169 std::cout << res2.error().message() << std::endl;
0170 }
0171
0172 double zResult1 = 0;
0173 if (res1.ok()) {
0174 BOOST_CHECK(!(*res1).empty());
0175 Vector3 result1 = (*res1).back().position();
0176 if (debugMode) {
0177 std::cout << "Vertex position result 1: " << result1.transpose()
0178 << std::endl;
0179 }
0180 CHECK_CLOSE_ABS(result1[eZ], zVertexPos1, 1_mm);
0181 zResult1 = result1[eZ];
0182 }
0183
0184 double zResult2 = 0;
0185 if (res2.ok()) {
0186 BOOST_CHECK(!(*res2).empty());
0187 Vector3 result2 = (*res2).back().position();
0188 if (debugMode) {
0189 std::cout << "Vertex position result 2: " << result2.transpose()
0190 << std::endl;
0191 }
0192 CHECK_CLOSE_ABS(result2[eZ], zVertexPos1, 1_mm);
0193 zResult2 = result2[eZ];
0194 }
0195
0196
0197 CHECK_CLOSE_REL(zResult1, zResult2, 1e-5);
0198 }
0199
0200 BOOST_AUTO_TEST_CASE(grid_density_vertex_finder_track_caching_test) {
0201 bool debugMode = false;
0202
0203 const int mainGridSize = 3001;
0204 const int trkGridSize = 35;
0205
0206 Covariance covMat = Covariance::Identity();
0207
0208
0209 Vector3 pos0{0, 0, 0};
0210 std::shared_ptr<PerigeeSurface> perigeeSurface =
0211 Surface::makeShared<PerigeeSurface>(pos0);
0212
0213 VertexingOptions vertexingOptions(geoContext, magFieldContext);
0214
0215 using Finder1 = GridDensityVertexFinder;
0216 using GridDensity = GaussianGridTrackDensity;
0217
0218
0219 GridDensity::Config densityConfig(100_mm, mainGridSize, trkGridSize);
0220 densityConfig.useHighestSumZPosition = true;
0221 GridDensity density(densityConfig);
0222
0223 Finder1::Config cfg(density);
0224 cfg.cacheGridStateForTrackRemoval = true;
0225 cfg.extractParameters.connect<&InputTrack::extractParameters>();
0226 Finder1 finder1(cfg);
0227
0228
0229 AdaptiveGridTrackDensity::Config adaptiveDensityConfig;
0230 adaptiveDensityConfig.spatialTrkGridSizeRange = {trkGridSize, trkGridSize};
0231 adaptiveDensityConfig.spatialBinExtent = 2. / 30.01 * 1_mm;
0232 adaptiveDensityConfig.useHighestSumZPosition = true;
0233 AdaptiveGridTrackDensity adaptiveDensity(adaptiveDensityConfig);
0234
0235 using Finder2 = AdaptiveGridDensityVertexFinder;
0236 Finder2::Config cfg2(adaptiveDensity);
0237 cfg2.cacheGridStateForTrackRemoval = true;
0238 cfg2.extractParameters.connect<&InputTrack::extractParameters>();
0239 Finder2 finder2(cfg2);
0240
0241 int mySeed = 31415;
0242 std::mt19937 gen(mySeed);
0243 unsigned int nTracks = 200;
0244
0245 std::vector<BoundTrackParameters> trackVec;
0246 trackVec.reserve(nTracks);
0247
0248
0249 for (unsigned int i = 0; i < nTracks; i++) {
0250
0251 Vector3 pos(xdist(gen), ydist(gen), 0);
0252
0253
0254 double pt = pTDist(gen);
0255 double phi = phiDist(gen);
0256 double eta = etaDist(gen);
0257 double charge = std::copysign(1., etaDist(gen));
0258
0259
0260 Vector3 direction = makeDirectionFromPhiEta(phi, eta);
0261 Intersection3D intersection =
0262 perigeeSurface->intersect(geoContext, pos, direction).closest();
0263 pos = intersection.position();
0264
0265
0266
0267 pos[eZ] = ((i % 4) == 0) ? z2dist(gen) : z1dist(gen);
0268
0269 trackVec.push_back(BoundTrackParameters::create(
0270 geoContext, perigeeSurface, makeVector4(pos, 0),
0271 direction, charge / pt, covMat,
0272 ParticleHypothesis::pion())
0273 .value());
0274 }
0275
0276 std::vector<InputTrack> inputTracks;
0277 for (const auto& trk : trackVec) {
0278 inputTracks.emplace_back(&trk);
0279 }
0280
0281 IVertexFinder::State state1 = finder1.makeState(magFieldContext);
0282 IVertexFinder::State state2 = finder2.makeState(magFieldContext);
0283
0284 double zResult1 = 0;
0285 double zResult2 = 0;
0286
0287 auto res1 = finder1.find(inputTracks, vertexingOptions, state1);
0288 if (!res1.ok()) {
0289 std::cout << res1.error().message() << std::endl;
0290 }
0291 if (res1.ok()) {
0292 BOOST_CHECK(!(*res1).empty());
0293 Vector3 result = (*res1).back().position();
0294 if (debugMode) {
0295 std::cout << "Vertex position after first fill 1: " << result.transpose()
0296 << std::endl;
0297 }
0298 CHECK_CLOSE_ABS(result[eZ], zVertexPos1, 1_mm);
0299 zResult1 = result[eZ];
0300 }
0301
0302 auto res2 = finder2.find(inputTracks, vertexingOptions, state2);
0303 if (!res2.ok()) {
0304 std::cout << res2.error().message() << std::endl;
0305 }
0306 if (res2.ok()) {
0307 BOOST_CHECK(!(*res2).empty());
0308 Vector3 result = (*res2).back().position();
0309 if (debugMode) {
0310 std::cout << "Vertex position after first fill 2: " << result.transpose()
0311 << std::endl;
0312 }
0313 CHECK_CLOSE_ABS(result[eZ], zVertexPos1, 1_mm);
0314 zResult2 = result[eZ];
0315 }
0316
0317 CHECK_CLOSE_REL(zResult1, zResult2, 1e-5);
0318
0319 int trkCount = 0;
0320 std::vector<InputTrack> removedTracks;
0321 for (const auto& trk : trackVec) {
0322 if ((trkCount % 4) != 0) {
0323 removedTracks.emplace_back(&trk);
0324 }
0325 trkCount++;
0326 }
0327
0328 state1.as<Finder1::State>().tracksToRemove = removedTracks;
0329 state2.as<Finder2::State>().tracksToRemove = removedTracks;
0330
0331 auto res3 = finder1.find(inputTracks, vertexingOptions, state1);
0332 if (!res3.ok()) {
0333 std::cout << res3.error().message() << std::endl;
0334 }
0335 if (res3.ok()) {
0336 BOOST_CHECK(!(*res3).empty());
0337 Vector3 result = (*res3).back().position();
0338 if (debugMode) {
0339 std::cout
0340 << "Vertex position after removing tracks near first density peak 1: "
0341 << result << std::endl;
0342 }
0343 CHECK_CLOSE_ABS(result[eZ], zVertexPos2, 1_mm);
0344 zResult1 = result[eZ];
0345 }
0346
0347 auto res4 = finder2.find(inputTracks, vertexingOptions, state2);
0348 if (!res4.ok()) {
0349 std::cout << res4.error().message() << std::endl;
0350 }
0351 if (res4.ok()) {
0352 BOOST_CHECK(!(*res4).empty());
0353 Vector3 result = (*res4).back().position();
0354 if (debugMode) {
0355 std::cout
0356 << "Vertex position after removing tracks near first density peak 2: "
0357 << result << std::endl;
0358 }
0359 CHECK_CLOSE_ABS(result[eZ], zVertexPos2, 1_mm);
0360 zResult2 = result[eZ];
0361 }
0362
0363 CHECK_CLOSE_REL(zResult1, zResult2, 1e-5);
0364 }
0365
0366
0367
0368
0369 BOOST_AUTO_TEST_CASE(grid_density_vertex_finder_seed_width_test) {
0370 bool debugMode = false;
0371
0372 const int mainGridSize = 3001;
0373 const int trkGridSize = 35;
0374
0375 Covariance covMat = Covariance::Identity();
0376
0377
0378 Vector3 pos0{0, 0, 0};
0379 std::shared_ptr<PerigeeSurface> perigeeSurface =
0380 Surface::makeShared<PerigeeSurface>(pos0);
0381
0382 VertexingOptions vertexingOptions(geoContext, magFieldContext);
0383 Vertex constraintVtx;
0384 constraintVtx.setCovariance(SquareMatrix3::Identity());
0385 vertexingOptions.constraint = constraintVtx;
0386
0387 using Finder1 = GridDensityVertexFinder;
0388 GaussianGridTrackDensity::Config gDensityConfig(100, mainGridSize,
0389 trkGridSize);
0390 GaussianGridTrackDensity gDensity(gDensityConfig);
0391 Finder1::Config cfg1(gDensity);
0392 cfg1.cacheGridStateForTrackRemoval = false;
0393 cfg1.estimateSeedWidth = true;
0394 cfg1.extractParameters.connect<&InputTrack::extractParameters>();
0395 Finder1 finder1(cfg1);
0396 IVertexFinder::State state1 = finder1.makeState(magFieldContext);
0397
0398
0399 AdaptiveGridTrackDensity::Config adaptiveDensityConfig;
0400 adaptiveDensityConfig.spatialTrkGridSizeRange = {trkGridSize, trkGridSize};
0401 adaptiveDensityConfig.spatialBinExtent = 2. / 30.01 * 1_mm;
0402 AdaptiveGridTrackDensity adaptiveDensity(adaptiveDensityConfig);
0403
0404 using Finder2 = AdaptiveGridDensityVertexFinder;
0405 Finder2::Config cfg2(adaptiveDensity);
0406 cfg2.cacheGridStateForTrackRemoval = false;
0407 cfg2.estimateSeedWidth = true;
0408 cfg2.extractParameters.connect<&InputTrack::extractParameters>();
0409 Finder2 finder2(cfg2);
0410 IVertexFinder::State state2 = finder2.makeState(magFieldContext);
0411
0412 int mySeed = 31415;
0413 std::mt19937 gen(mySeed);
0414 unsigned int nTracks = 20;
0415
0416 std::vector<BoundTrackParameters> trackVec;
0417 trackVec.reserve(nTracks);
0418
0419
0420 for (unsigned int i = 0; i < nTracks; i++) {
0421
0422 Vector3 pos(xdist(gen), ydist(gen), 0);
0423
0424
0425 double pt = pTDist(gen);
0426 double phi = phiDist(gen);
0427 double eta = etaDist(gen);
0428 double charge = std::copysign(1., etaDist(gen));
0429
0430
0431 Vector3 direction = makeDirectionFromPhiEta(phi, eta);
0432 Intersection3D intersection =
0433 perigeeSurface->intersect(geoContext, pos, direction).closest();
0434 pos = intersection.position();
0435
0436 pos[eZ] = z1dist(gen);
0437
0438 trackVec.push_back(BoundTrackParameters::create(
0439 geoContext, perigeeSurface, makeVector4(pos, 0),
0440 direction, charge / pt, covMat,
0441 ParticleHypothesis::pion())
0442 .value());
0443 }
0444
0445 std::vector<InputTrack> inputTracks;
0446 for (const auto& trk : trackVec) {
0447 inputTracks.emplace_back(&trk);
0448 }
0449
0450
0451 auto res1 = finder1.find(inputTracks, vertexingOptions, state1);
0452 if (!res1.ok()) {
0453 std::cout << res1.error().message() << std::endl;
0454 }
0455
0456 double covZZ1 = 0;
0457 if (res1.ok()) {
0458 BOOST_CHECK(!(*res1).empty());
0459 SquareMatrix3 cov = (*res1).back().covariance();
0460 BOOST_CHECK_NE(constraintVtx.covariance(), cov);
0461 BOOST_CHECK_NE(cov(eZ, eZ), 0.);
0462 covZZ1 = cov(eZ, eZ);
0463 if (debugMode) {
0464 std::cout << "Estimated z-seed width 1: " << cov(eZ, eZ) << std::endl;
0465 }
0466 }
0467
0468
0469 auto res2 = finder2.find(inputTracks, vertexingOptions, state2);
0470 if (!res2.ok()) {
0471 std::cout << res2.error().message() << std::endl;
0472 }
0473
0474 double covZZ2 = 0;
0475 if (res2.ok()) {
0476 BOOST_CHECK(!(*res2).empty());
0477 SquareMatrix3 cov = (*res2).back().covariance();
0478 BOOST_CHECK_NE(constraintVtx.covariance(), cov);
0479 BOOST_CHECK_NE(cov(eZ, eZ), 0.);
0480 covZZ2 = cov(eZ, eZ);
0481 if (debugMode) {
0482 std::cout << "Estimated z-seed width 2: " << cov(eZ, eZ) << std::endl;
0483 }
0484 }
0485
0486
0487 CHECK_CLOSE_ABS(covZZ1, covZZ2, 1e-4);
0488 }
0489
0490 BOOST_AUTO_TEST_SUITE_END()
0491
0492 }