Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-11 07:51:33

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/unit_test.hpp>
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Direction.hpp"
0013 #include "Acts/Definitions/TrackParametrization.hpp"
0014 #include "Acts/Definitions/Units.hpp"
0015 #include "Acts/EventData/GenericBoundTrackParameters.hpp"
0016 #include "Acts/EventData/TrackParameters.hpp"
0017 #include "Acts/Geometry/GeometryContext.hpp"
0018 #include "Acts/Geometry/GeometryIdentifier.hpp"
0019 #include "Acts/MagneticField/ConstantBField.hpp"
0020 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0021 #include "Acts/Propagator/EigenStepper.hpp"
0022 #include "Acts/Propagator/Propagator.hpp"
0023 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0024 #include "Acts/Utilities/AnnealingUtility.hpp"
0025 #include "Acts/Utilities/Helpers.hpp"
0026 #include "Acts/Utilities/Result.hpp"
0027 #include "Acts/Vertexing/AdaptiveGridDensityVertexFinder.hpp"
0028 #include "Acts/Vertexing/AdaptiveMultiVertexFinder.hpp"
0029 #include "Acts/Vertexing/AdaptiveMultiVertexFitter.hpp"
0030 #include "Acts/Vertexing/GaussianTrackDensity.hpp"
0031 #include "Acts/Vertexing/GridDensityVertexFinder.hpp"
0032 #include "Acts/Vertexing/HelicalTrackLinearizer.hpp"
0033 #include "Acts/Vertexing/IVertexFinder.hpp"
0034 #include "Acts/Vertexing/ImpactPointEstimator.hpp"
0035 #include "Acts/Vertexing/TrackAtVertex.hpp"
0036 #include "Acts/Vertexing/TrackDensityVertexFinder.hpp"
0037 #include "Acts/Vertexing/Vertex.hpp"
0038 #include "Acts/Vertexing/VertexingOptions.hpp"
0039 
0040 #include <algorithm>
0041 #include <array>
0042 #include <chrono>
0043 #include <cmath>
0044 #include <functional>
0045 #include <iostream>
0046 #include <map>
0047 #include <memory>
0048 #include <numbers>
0049 #include <string>
0050 #include <system_error>
0051 #include <tuple>
0052 #include <utility>
0053 #include <vector>
0054 
0055 #include "VertexingDataHelper.hpp"
0056 
0057 using namespace Acts::UnitLiterals;
0058 
0059 namespace Acts::Test {
0060 
0061 using Covariance = BoundSquareMatrix;
0062 using Propagator = Acts::Propagator<EigenStepper<>>;
0063 using Linearizer = HelicalTrackLinearizer;
0064 
0065 // Create a test context
0066 GeometryContext geoContext = GeometryContext();
0067 MagneticFieldContext magFieldContext = MagneticFieldContext();
0068 
0069 const std::string toolString = "AMVF";
0070 
0071 /// @brief AMVF test with Gaussian seed finder
0072 BOOST_AUTO_TEST_CASE(adaptive_multi_vertex_finder_test) {
0073   // Set debug mode
0074   bool debugMode = false;
0075   // Set up constant B-Field
0076   auto bField = std::make_shared<ConstantBField>(Vector3(0., 0., 2_T));
0077 
0078   // Set up EigenStepper
0079   // EigenStepper<> stepper(bField);
0080   EigenStepper<> stepper(bField);
0081 
0082   // Set up propagator with void navigator
0083   auto propagator = std::make_shared<Propagator>(stepper);
0084 
0085   // IP 3D Estimator
0086   ImpactPointEstimator::Config ipEstimatorCfg(bField, propagator);
0087   ImpactPointEstimator ipEstimator(ipEstimatorCfg);
0088 
0089   std::vector<double> temperatures{
0090       8., 4., 2., std::numbers::sqrt2, std::sqrt(3. / 2.), 1.};
0091   AnnealingUtility::Config annealingConfig;
0092   annealingConfig.setOfTemperatures = temperatures;
0093   AnnealingUtility annealingUtility(annealingConfig);
0094 
0095   using Fitter = AdaptiveMultiVertexFitter;
0096 
0097   Fitter::Config fitterCfg(ipEstimator);
0098 
0099   fitterCfg.annealingTool = annealingUtility;
0100 
0101   // Linearizer for BoundTrackParameters type test
0102   Linearizer::Config ltConfig;
0103   ltConfig.bField = bField;
0104   ltConfig.propagator = propagator;
0105   Linearizer linearizer(ltConfig);
0106 
0107   // Test smoothing
0108   fitterCfg.doSmoothing = true;
0109   fitterCfg.extractParameters.connect<&InputTrack::extractParameters>();
0110   fitterCfg.trackLinearizer.connect<&Linearizer::linearizeTrack>(&linearizer);
0111 
0112   Fitter fitter(fitterCfg);
0113 
0114   GaussianTrackDensity::Config densityCfg;
0115   densityCfg.extractParameters.connect<&InputTrack::extractParameters>();
0116   auto seedFinder = std::make_shared<TrackDensityVertexFinder>(
0117       TrackDensityVertexFinder::Config{Acts::GaussianTrackDensity(densityCfg)});
0118 
0119   AdaptiveMultiVertexFinder::Config finderConfig(std::move(fitter), seedFinder,
0120                                                  ipEstimator, bField);
0121   finderConfig.extractParameters.connect<&InputTrack::extractParameters>();
0122 
0123   AdaptiveMultiVertexFinder finder(std::move(finderConfig));
0124   IVertexFinder::State state = finder.makeState(magFieldContext);
0125 
0126   auto csvData = readTracksAndVertexCSV(toolString);
0127   std::vector<BoundTrackParameters> tracks = std::get<TracksData>(csvData);
0128 
0129   if (debugMode) {
0130     std::cout << "Number of tracks in event: " << tracks.size() << std::endl;
0131     int maxCout = 10;
0132     int count = 0;
0133     for (const auto& trk : tracks) {
0134       std::cout << count << ". track: " << std::endl;
0135       std::cout << "params: " << trk << std::endl;
0136       count++;
0137       if (count == maxCout) {
0138         break;
0139       }
0140     }
0141   }
0142 
0143   std::vector<InputTrack> inputTracks;
0144   for (const auto& trk : tracks) {
0145     inputTracks.emplace_back(&trk);
0146   }
0147 
0148   // TODO: test without using beam spot constraint
0149   Vertex bsConstr = std::get<BeamSpotData>(csvData);
0150   VertexingOptions vertexingOptions(geoContext, magFieldContext, bsConstr);
0151 
0152   auto t1 = std::chrono::system_clock::now();
0153   auto findResult = finder.find(inputTracks, vertexingOptions, state);
0154   auto t2 = std::chrono::system_clock::now();
0155 
0156   auto timediff =
0157       std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
0158 
0159   if (!findResult.ok()) {
0160     std::cout << findResult.error().message() << std::endl;
0161   }
0162 
0163   BOOST_CHECK(findResult.ok());
0164 
0165   std::vector<Vertex> allVertices = *findResult;
0166 
0167   if (debugMode) {
0168     std::cout << "Time needed: " << timediff << " ms." << std::endl;
0169     std::cout << "Number of vertices reconstructed: " << allVertices.size()
0170               << std::endl;
0171 
0172     int count = 0;
0173     for (const auto& vtx : allVertices) {
0174       count++;
0175       std::cout << count << ". Vertex at position: " << vtx.position()[0]
0176                 << ", " << vtx.position()[1] << ", " << vtx.position()[2]
0177                 << std::endl;
0178       std::cout << count << ". Vertex with cov: " << vtx.covariance()
0179                 << std::endl;
0180       std::cout << "\t with n tracks: " << vtx.tracks().size() << std::endl;
0181     }
0182   }
0183 
0184   // Test expected outcomes from athena implementation
0185   // Number of reconstructed vertices
0186   auto verticesInfo = std::get<VerticesData>(csvData);
0187   const int expNRecoVertices = verticesInfo.size();
0188 
0189   BOOST_CHECK_EQUAL(allVertices.size(), expNRecoVertices);
0190 
0191   double relTol = 1e-2;
0192   double small = 1e-3;
0193   for (int i = 0; i < expNRecoVertices; i++) {
0194     auto recoVtx = allVertices[i];
0195     auto expVtx = verticesInfo[i];
0196     CHECK_CLOSE_OR_SMALL(recoVtx.position(), expVtx.position, relTol, small);
0197     CHECK_CLOSE_OR_SMALL(recoVtx.covariance(), expVtx.covariance, relTol,
0198                          small);
0199     BOOST_CHECK_EQUAL(recoVtx.tracks().size(), expVtx.nTracks);
0200     CHECK_CLOSE_OR_SMALL(recoVtx.tracks()[0].trackWeight, expVtx.trk1Weight,
0201                          relTol, small);
0202     CHECK_CLOSE_OR_SMALL(recoVtx.tracks()[0].vertexCompatibility,
0203                          expVtx.trk1Comp, relTol, small);
0204   }
0205 }
0206 
0207 // Dummy user-defined InputTrackStub type
0208 struct InputTrackStub {
0209   InputTrackStub(const BoundTrackParameters& params, int id)
0210       : m_parameters(params), m_id(id) {}
0211 
0212   const BoundTrackParameters& parameters() const { return m_parameters; }
0213   // store e.g. link to original objects here
0214 
0215   int id() const { return m_id; }
0216 
0217  private:
0218   BoundTrackParameters m_parameters;
0219 
0220   // Some test track ID
0221   int m_id;
0222 };
0223 
0224 /// @brief AMVF test with user-defined input track type
0225 BOOST_AUTO_TEST_CASE(adaptive_multi_vertex_finder_usertype_test) {
0226   // Set debug mode
0227   bool debugMode = false;
0228   // Set up constant B-Field
0229   auto bField = std::make_shared<ConstantBField>(Vector3(0., 0., 2_T));
0230 
0231   // Set up EigenStepper
0232   // EigenStepper<> stepper(bField);
0233   EigenStepper<> stepper(bField);
0234 
0235   // Set up propagator with void navigator
0236   auto propagator = std::make_shared<Propagator>(stepper);
0237 
0238   // Create a custom std::function to extract BoundTrackParameters from
0239   // user-defined InputTrackStub
0240   auto extractParameters = [](const InputTrack& track) {
0241     return track.as<InputTrackStub>()->parameters();
0242   };
0243 
0244   // IP 3D Estimator
0245   ImpactPointEstimator::Config ipEstimatorCfg(bField, propagator);
0246   ImpactPointEstimator ipEstimator(ipEstimatorCfg);
0247 
0248   std::vector<double> temperatures{
0249       8., 4., 2., std::numbers::sqrt2, std::sqrt(3. / 2.), 1.};
0250   AnnealingUtility::Config annealingConfig;
0251   annealingConfig.setOfTemperatures = temperatures;
0252   AnnealingUtility annealingUtility(annealingConfig);
0253 
0254   using Fitter = AdaptiveMultiVertexFitter;
0255 
0256   Fitter::Config fitterCfg(ipEstimator);
0257 
0258   fitterCfg.annealingTool = annealingUtility;
0259 
0260   // Linearizer
0261   Linearizer::Config ltConfig;
0262   ltConfig.bField = bField;
0263   ltConfig.propagator = propagator;
0264   Linearizer linearizer(ltConfig);
0265 
0266   // Test smoothing
0267   fitterCfg.doSmoothing = true;
0268   fitterCfg.extractParameters.connect(extractParameters);
0269   fitterCfg.trackLinearizer.connect<&Linearizer::linearizeTrack>(&linearizer);
0270 
0271   Fitter fitter(fitterCfg);
0272 
0273   GaussianTrackDensity::Config densityCfg;
0274   densityCfg.extractParameters.connect(extractParameters);
0275   auto seedFinder = std::make_shared<TrackDensityVertexFinder>(
0276       TrackDensityVertexFinder::Config{Acts::GaussianTrackDensity(densityCfg)});
0277 
0278   AdaptiveMultiVertexFinder::Config finderConfig(
0279       std::move(fitter), std::move(seedFinder), ipEstimator, bField);
0280   finderConfig.extractParameters.connect(extractParameters);
0281 
0282   AdaptiveMultiVertexFinder finder(std::move(finderConfig));
0283   IVertexFinder::State state = finder.makeState(magFieldContext);
0284 
0285   auto csvData = readTracksAndVertexCSV(toolString);
0286   auto tracks = std::get<TracksData>(csvData);
0287 
0288   std::vector<InputTrackStub> userTracks;
0289   int idCount = 0;
0290   for (const auto& trk : tracks) {
0291     userTracks.push_back(InputTrackStub(trk, idCount));
0292     idCount++;
0293   }
0294 
0295   if (debugMode) {
0296     std::cout << "Number of tracks in event: " << tracks.size() << std::endl;
0297     int maxCout = 10;
0298     int count = 0;
0299     for (const auto& trk : tracks) {
0300       std::cout << count << ". track: " << std::endl;
0301       std::cout << "params: " << trk << std::endl;
0302       count++;
0303       if (count == maxCout) {
0304         break;
0305       }
0306     }
0307   }
0308 
0309   std::vector<InputTrack> userInputTracks;
0310   for (const auto& trk : userTracks) {
0311     userInputTracks.emplace_back(&trk);
0312   }
0313 
0314   Vertex constraintVtx;
0315   constraintVtx.setPosition(std::get<BeamSpotData>(csvData).position());
0316   constraintVtx.setCovariance(std::get<BeamSpotData>(csvData).covariance());
0317 
0318   VertexingOptions vertexingOptions(geoContext, magFieldContext, constraintVtx);
0319 
0320   auto findResult = finder.find(userInputTracks, vertexingOptions, state);
0321 
0322   if (!findResult.ok()) {
0323     std::cout << findResult.error().message() << std::endl;
0324   }
0325 
0326   BOOST_CHECK(findResult.ok());
0327 
0328   std::vector<Vertex> allVertices = *findResult;
0329 
0330   if (debugMode) {
0331     std::cout << "Number of vertices reconstructed: " << allVertices.size()
0332               << std::endl;
0333 
0334     int count = 0;
0335     for (const auto& vtx : allVertices) {
0336       count++;
0337       std::cout << count << ". Vertex at position: " << vtx.position()[0]
0338                 << ", " << vtx.position()[1] << ", " << vtx.position()[2]
0339                 << std::endl;
0340       std::cout << count << ". Vertex with cov: " << vtx.covariance()
0341                 << std::endl;
0342       std::cout << "\t with n tracks: " << vtx.tracks().size() << std::endl;
0343     }
0344     for (auto& trk : allVertices[0].tracks()) {
0345       std::cout << "Track ID at first vertex: "
0346                 << trk.originalParams.as<InputTrackStub>()->id() << std::endl;
0347     }
0348   }
0349 
0350   auto verticesInfo = std::get<VerticesData>(csvData);
0351   const int expNRecoVertices = verticesInfo.size();
0352 
0353   BOOST_CHECK_EQUAL(allVertices.size(), expNRecoVertices);
0354 
0355   double relTol = 1e-2;
0356   double small = 1e-3;
0357   for (int i = 0; i < expNRecoVertices; i++) {
0358     auto recoVtx = allVertices[i];
0359     auto expVtx = verticesInfo[i];
0360     CHECK_CLOSE_OR_SMALL(recoVtx.position(), expVtx.position, relTol, small);
0361     CHECK_CLOSE_OR_SMALL(recoVtx.covariance(), expVtx.covariance, relTol,
0362                          small);
0363     BOOST_CHECK_EQUAL(recoVtx.tracks().size(), expVtx.nTracks);
0364     CHECK_CLOSE_OR_SMALL(recoVtx.tracks()[0].trackWeight, expVtx.trk1Weight,
0365                          relTol, small);
0366     CHECK_CLOSE_OR_SMALL(recoVtx.tracks()[0].vertexCompatibility,
0367                          expVtx.trk1Comp, relTol, small);
0368   }
0369 }
0370 
0371 /// @brief AMVF test with grid seed finder
0372 BOOST_AUTO_TEST_CASE(adaptive_multi_vertex_finder_grid_seed_finder_test) {
0373   // Set debug mode
0374   bool debugMode = false;
0375   if (debugMode) {
0376     std::cout << "Starting AMVF test with grid seed finder..." << std::endl;
0377   }
0378   // Set up constant B-Field
0379   auto bField = std::make_shared<ConstantBField>(Vector3(0., 0., 2_T));
0380 
0381   // Set up EigenStepper
0382   // EigenStepper<> stepper(bField);
0383   EigenStepper<> stepper(bField);
0384 
0385   // Set up propagator with void navigator
0386   auto propagator = std::make_shared<Propagator>(stepper);
0387 
0388   // IP Estimator
0389   ImpactPointEstimator::Config ipEstCfg(bField, propagator);
0390   ImpactPointEstimator ipEst(ipEstCfg);
0391 
0392   std::vector<double> temperatures{
0393       8., 4., 2., std::numbers::sqrt2, std::sqrt(3. / 2.), 1.};
0394   AnnealingUtility::Config annealingConfig;
0395   annealingConfig.setOfTemperatures = temperatures;
0396   AnnealingUtility annealingUtility(annealingConfig);
0397 
0398   using Fitter = AdaptiveMultiVertexFitter;
0399 
0400   Fitter::Config fitterCfg(ipEst);
0401 
0402   fitterCfg.annealingTool = annealingUtility;
0403 
0404   // Linearizer for BoundTrackParameters type test
0405   Linearizer::Config ltConfig;
0406   ltConfig.bField = bField;
0407   ltConfig.propagator = propagator;
0408   Linearizer linearizer(ltConfig);
0409 
0410   // Test smoothing
0411   fitterCfg.doSmoothing = true;
0412   fitterCfg.extractParameters.connect<&InputTrack::extractParameters>();
0413   fitterCfg.trackLinearizer.connect<&Linearizer::linearizeTrack>(&linearizer);
0414 
0415   Fitter fitter(fitterCfg);
0416 
0417   using SeedFinder = GridDensityVertexFinder;
0418   GaussianGridTrackDensity::Config gDensityConfig(250, 4000, 55);
0419   GaussianGridTrackDensity gDensity(gDensityConfig);
0420   SeedFinder::Config seedFinderCfg(gDensity);
0421   seedFinderCfg.cacheGridStateForTrackRemoval = true;
0422   seedFinderCfg.extractParameters.connect<&InputTrack::extractParameters>();
0423 
0424   auto seedFinder = std::make_shared<SeedFinder>(seedFinderCfg);
0425 
0426   AdaptiveMultiVertexFinder::Config finderConfig(
0427       std::move(fitter), std::move(seedFinder), ipEst, bField);
0428   finderConfig.extractParameters.connect<&InputTrack::extractParameters>();
0429 
0430   AdaptiveMultiVertexFinder finder(std::move(finderConfig));
0431   IVertexFinder::State state = finder.makeState(magFieldContext);
0432 
0433   auto csvData = readTracksAndVertexCSV(toolString);
0434   auto tracks = std::get<TracksData>(csvData);
0435 
0436   if (debugMode) {
0437     std::cout << "Number of tracks in event: " << tracks.size() << std::endl;
0438     int maxCout = 10;
0439     int count = 0;
0440     for (const auto& trk : tracks) {
0441       std::cout << count << ". track: " << std::endl;
0442       std::cout << "params: " << trk << std::endl;
0443       count++;
0444       if (count == maxCout) {
0445         break;
0446       }
0447     }
0448   }
0449 
0450   std::vector<InputTrack> inputTracks;
0451   for (const auto& trk : tracks) {
0452     inputTracks.emplace_back(&trk);
0453   }
0454 
0455   // TODO: test using beam spot constraint
0456   Vertex bsConstr = std::get<BeamSpotData>(csvData);
0457   VertexingOptions vertexingOptions(geoContext, magFieldContext, bsConstr);
0458 
0459   auto t1 = std::chrono::system_clock::now();
0460   auto findResult = finder.find(inputTracks, vertexingOptions, state);
0461   auto t2 = std::chrono::system_clock::now();
0462 
0463   auto timediff =
0464       std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
0465 
0466   if (!findResult.ok()) {
0467     std::cout << findResult.error().message() << std::endl;
0468   }
0469 
0470   BOOST_CHECK(findResult.ok());
0471 
0472   std::vector<Vertex> allVertices = *findResult;
0473 
0474   if (debugMode) {
0475     std::cout << "Time needed: " << timediff << " ms." << std::endl;
0476     std::cout << "Number of vertices reconstructed: " << allVertices.size()
0477               << std::endl;
0478 
0479     int count = 0;
0480     for (const auto& vtx : allVertices) {
0481       count++;
0482       std::cout << count << ". Vertex at position: " << vtx.position()[0]
0483                 << ", " << vtx.position()[1] << ", " << vtx.position()[2]
0484                 << std::endl;
0485       std::cout << count << ". Vertex with cov: " << vtx.covariance()
0486                 << std::endl;
0487       std::cout << "\t with n tracks: " << vtx.tracks().size() << std::endl;
0488     }
0489   }
0490   // Test expected outcomes from athena implementation
0491   // Number of reconstructed vertices
0492   auto verticesInfo = std::get<VerticesData>(csvData);
0493   const int expNRecoVertices = verticesInfo.size();
0494 
0495   BOOST_CHECK_EQUAL(allVertices.size(), expNRecoVertices);
0496   std::vector<bool> vtxFound(expNRecoVertices, false);
0497 
0498   for (const auto& vtx : allVertices) {
0499     double vtxZ = vtx.position()[2];
0500     double diffZ = 1e5;
0501     int foundVtxIdx = -1;
0502     for (int i = 0; i < expNRecoVertices; i++) {
0503       if (!vtxFound[i]) {
0504         if (std::abs(vtxZ - verticesInfo[i].position[2]) < diffZ) {
0505           diffZ = std::abs(vtxZ - verticesInfo[i].position[2]);
0506           foundVtxIdx = i;
0507         }
0508       }
0509     }
0510     if (diffZ < 0.5_mm) {
0511       vtxFound[foundVtxIdx] = true;
0512       CHECK_CLOSE_ABS(vtx.tracks().size(), verticesInfo[foundVtxIdx].nTracks,
0513                       1);
0514     }
0515   }
0516   for (bool found : vtxFound) {
0517     BOOST_CHECK_EQUAL(found, true);
0518   }
0519 }
0520 
0521 /// @brief AMVF test with adaptive grid seed finder
0522 BOOST_AUTO_TEST_CASE(
0523     adaptive_multi_vertex_finder_adaptive_grid_seed_finder_test) {
0524   // Set debug mode
0525   bool debugMode = false;
0526   if (debugMode) {
0527     std::cout << "Starting AMVF test with adaptive grid seed finder..."
0528               << std::endl;
0529   }
0530   // Set up constant B-Field
0531   auto bField = std::make_shared<ConstantBField>(Vector3(0., 0., 2_T));
0532 
0533   // Set up EigenStepper
0534   // EigenStepper<> stepper(bField);
0535   EigenStepper<> stepper(bField);
0536 
0537   // Set up propagator with void navigator
0538   auto propagator = std::make_shared<Propagator>(stepper);
0539 
0540   // IP Estimator
0541   ImpactPointEstimator::Config ipEstCfg(bField, propagator);
0542   ImpactPointEstimator ipEst(ipEstCfg);
0543 
0544   std::vector<double> temperatures{
0545       8., 4., 2., std::numbers::sqrt2, std::sqrt(3. / 2.), 1.};
0546   AnnealingUtility::Config annealingConfig;
0547   annealingConfig.setOfTemperatures = temperatures;
0548   AnnealingUtility annealingUtility(annealingConfig);
0549 
0550   using Fitter = AdaptiveMultiVertexFitter;
0551 
0552   Fitter::Config fitterCfg(ipEst);
0553 
0554   fitterCfg.annealingTool = annealingUtility;
0555 
0556   // Linearizer for BoundTrackParameters type test
0557   Linearizer::Config ltConfig;
0558   ltConfig.bField = bField;
0559   ltConfig.propagator = propagator;
0560   Linearizer linearizer(ltConfig);
0561 
0562   // Test smoothing
0563   fitterCfg.doSmoothing = true;
0564   fitterCfg.extractParameters.connect<&InputTrack::extractParameters>();
0565   fitterCfg.trackLinearizer.connect<&Linearizer::linearizeTrack>(&linearizer);
0566 
0567   Fitter fitter(fitterCfg);
0568 
0569   // Grid density used during vertex seed finding
0570   AdaptiveGridTrackDensity::Config gridDensityCfg;
0571   // force track to have exactly spatialTrkGridSize spatial bins for testing
0572   // purposes
0573   gridDensityCfg.spatialTrkGridSizeRange = {55, 55};
0574   gridDensityCfg.spatialBinExtent = 0.05;
0575   AdaptiveGridTrackDensity gridDensity(gridDensityCfg);
0576 
0577   using SeedFinder = AdaptiveGridDensityVertexFinder;
0578   SeedFinder::Config seedFinderCfg(gridDensity);
0579   seedFinderCfg.cacheGridStateForTrackRemoval = true;
0580   seedFinderCfg.extractParameters.connect<&InputTrack::extractParameters>();
0581 
0582   auto seedFinder = std::make_shared<SeedFinder>(seedFinderCfg);
0583 
0584   AdaptiveMultiVertexFinder::Config finderConfig(
0585       std::move(fitter), std::move(seedFinder), ipEst, bField);
0586   finderConfig.extractParameters.connect<&InputTrack::extractParameters>();
0587 
0588   AdaptiveMultiVertexFinder finder(std::move(finderConfig));
0589   IVertexFinder::State state = finder.makeState(magFieldContext);
0590 
0591   auto csvData = readTracksAndVertexCSV(toolString);
0592   auto tracks = std::get<TracksData>(csvData);
0593 
0594   if (debugMode) {
0595     std::cout << "Number of tracks in event: " << tracks.size() << std::endl;
0596     int maxCout = 10;
0597     int count = 0;
0598     for (const auto& trk : tracks) {
0599       std::cout << count << ". track: " << std::endl;
0600       std::cout << "params: " << trk << std::endl;
0601       count++;
0602       if (count == maxCout) {
0603         break;
0604       }
0605     }
0606   }
0607 
0608   std::vector<InputTrack> inputTracks;
0609   for (const auto& trk : tracks) {
0610     inputTracks.emplace_back(&trk);
0611   }
0612 
0613   Vertex bsConstr = std::get<BeamSpotData>(csvData);
0614   VertexingOptions vertexingOptions(geoContext, magFieldContext, bsConstr);
0615 
0616   auto t1 = std::chrono::system_clock::now();
0617   auto findResult = finder.find(inputTracks, vertexingOptions, state);
0618   auto t2 = std::chrono::system_clock::now();
0619 
0620   auto timediff =
0621       std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
0622 
0623   if (!findResult.ok()) {
0624     std::cout << findResult.error().message() << std::endl;
0625   }
0626 
0627   BOOST_CHECK(findResult.ok());
0628 
0629   std::vector<Vertex> allVertices = *findResult;
0630 
0631   if (debugMode) {
0632     std::cout << "Time needed: " << timediff << " ms." << std::endl;
0633     std::cout << "Number of vertices reconstructed: " << allVertices.size()
0634               << std::endl;
0635 
0636     int count = 0;
0637     for (const auto& vtx : allVertices) {
0638       count++;
0639       std::cout << count << ". Vertex at position: " << vtx.position()[0]
0640                 << ", " << vtx.position()[1] << ", " << vtx.position()[2]
0641                 << std::endl;
0642       std::cout << count << ". Vertex with cov: " << vtx.covariance()
0643                 << std::endl;
0644       std::cout << "\t with n tracks: " << vtx.tracks().size() << std::endl;
0645     }
0646   }
0647   // Test expected outcomes from athena implementation
0648   // Number of reconstructed vertices
0649   auto verticesInfo = std::get<VerticesData>(csvData);
0650   const int expNRecoVertices = verticesInfo.size();
0651 
0652   BOOST_CHECK_EQUAL(allVertices.size(), expNRecoVertices);
0653   std::vector<bool> vtxFound(expNRecoVertices, false);
0654 
0655   for (const auto& vtx : allVertices) {
0656     double vtxZ = vtx.position()[2];
0657     double diffZ = 1e5;
0658     int foundVtxIdx = -1;
0659     for (int i = 0; i < expNRecoVertices; i++) {
0660       if (!vtxFound[i]) {
0661         if (std::abs(vtxZ - verticesInfo[i].position[2]) < diffZ) {
0662           diffZ = std::abs(vtxZ - verticesInfo[i].position[2]);
0663           foundVtxIdx = i;
0664         }
0665       }
0666     }
0667     if (diffZ < 0.5_mm) {
0668       vtxFound[foundVtxIdx] = true;
0669       CHECK_CLOSE_ABS(vtx.tracks().size(), verticesInfo[foundVtxIdx].nTracks,
0670                       2);
0671     }
0672   }
0673   for (bool found : vtxFound) {
0674     BOOST_CHECK_EQUAL(found, true);
0675   }
0676 }
0677 
0678 }  // namespace Acts::Test