File indexing completed on 2025-01-18 09:13:01
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/Direction.hpp"
0013 #include "Acts/Definitions/TrackParametrization.hpp"
0014 #include "Acts/Definitions/Units.hpp"
0015 #include "Acts/EventData/Charge.hpp"
0016 #include "Acts/EventData/GenericBoundTrackParameters.hpp"
0017 #include "Acts/EventData/TrackParameters.hpp"
0018 #include "Acts/Geometry/GeometryContext.hpp"
0019 #include "Acts/Geometry/GeometryIdentifier.hpp"
0020 #include "Acts/MagneticField/ConstantBField.hpp"
0021 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0022 #include "Acts/Propagator/EigenStepper.hpp"
0023 #include "Acts/Propagator/Propagator.hpp"
0024 #include "Acts/Surfaces/PerigeeSurface.hpp"
0025 #include "Acts/Surfaces/Surface.hpp"
0026 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0027 #include "Acts/Utilities/AnnealingUtility.hpp"
0028 #include "Acts/Utilities/Logger.hpp"
0029 #include "Acts/Utilities/Result.hpp"
0030 #include "Acts/Vertexing/AMVFInfo.hpp"
0031 #include "Acts/Vertexing/AdaptiveMultiVertexFitter.hpp"
0032 #include "Acts/Vertexing/HelicalTrackLinearizer.hpp"
0033 #include "Acts/Vertexing/ImpactPointEstimator.hpp"
0034 #include "Acts/Vertexing/TrackAtVertex.hpp"
0035 #include "Acts/Vertexing/Vertex.hpp"
0036 #include "Acts/Vertexing/VertexingOptions.hpp"
0037
0038 #include <algorithm>
0039 #include <array>
0040 #include <cmath>
0041 #include <iostream>
0042 #include <map>
0043 #include <memory>
0044 #include <numbers>
0045 #include <random>
0046 #include <tuple>
0047 #include <type_traits>
0048 #include <utility>
0049 #include <vector>
0050
0051 using namespace Acts::UnitLiterals;
0052
0053 namespace Acts::Test {
0054
0055 using Acts::VectorHelpers::makeVector4;
0056
0057
0058 ACTS_LOCAL_LOGGER(Acts::getDefaultLogger("AMVFitterTests", Acts::Logging::INFO))
0059
0060 using Covariance = BoundSquareMatrix;
0061 using Propagator = Acts::Propagator<EigenStepper<>>;
0062 using Linearizer = HelicalTrackLinearizer;
0063
0064
0065 GeometryContext geoContext = GeometryContext();
0066 MagneticFieldContext magFieldContext = MagneticFieldContext();
0067
0068
0069 std::uniform_real_distribution<double> vXYDist(-0.1_mm, 0.1_mm);
0070
0071 std::uniform_real_distribution<double> vZDist(-20_mm, 20_mm);
0072
0073 std::uniform_real_distribution<double> d0Dist(-0.01_mm, 0.01_mm);
0074
0075 std::uniform_real_distribution<double> z0Dist(-0.2_mm, 0.2_mm);
0076
0077 std::uniform_real_distribution<double> pTDist(1._GeV, 30._GeV);
0078
0079 std::uniform_real_distribution<double> phiDist(-std::numbers::pi,
0080 std::numbers::pi);
0081
0082 std::uniform_real_distribution<double> thetaDist(1., std::numbers::pi - 1.);
0083
0084 std::uniform_real_distribution<double> qDist(-1, 1);
0085
0086
0087 std::uniform_real_distribution<double> relTDist(-4_ps, 4_ps);
0088
0089 std::uniform_real_distribution<double> resIPDist(0., 100._um);
0090
0091 std::uniform_real_distribution<double> resAngDist(0., 0.1);
0092
0093 std::uniform_real_distribution<double> resQoPDist(-0.1, 0.1);
0094
0095
0096 std::uniform_real_distribution<double> resTDist(0_ps, 8_ps);
0097
0098
0099
0100 BOOST_AUTO_TEST_CASE(adaptive_multi_vertex_fitter_test) {
0101
0102 int mySeed = 31415;
0103 std::mt19937 gen(mySeed);
0104
0105
0106 auto bField = std::make_shared<ConstantBField>(Vector3{0.0, 0.0, 1_T});
0107
0108
0109 EigenStepper<> stepper(bField);
0110
0111
0112 auto propagator = std::make_shared<Propagator>(stepper);
0113
0114 VertexingOptions vertexingOptions(geoContext, magFieldContext);
0115
0116
0117 ImpactPointEstimator::Config ip3dEstCfg(bField, propagator);
0118 ImpactPointEstimator ip3dEst(ip3dEstCfg);
0119
0120
0121 Linearizer::Config ltConfig;
0122 ltConfig.bField = bField;
0123 ltConfig.propagator = propagator;
0124 Linearizer linearizer(ltConfig);
0125
0126 AdaptiveMultiVertexFitter::Config fitterCfg(ip3dEst);
0127 fitterCfg.trackLinearizer.connect<&Linearizer::linearizeTrack>(&linearizer);
0128
0129
0130 fitterCfg.doSmoothing = true;
0131 fitterCfg.extractParameters.connect<&InputTrack::extractParameters>();
0132
0133 AdaptiveMultiVertexFitter fitter(std::move(fitterCfg));
0134
0135
0136
0137 Vector3 vtxPos1(-0.15_mm, -0.1_mm, -1.5_mm);
0138 Vector3 vtxPos2(-0.1_mm, -0.15_mm, -3._mm);
0139 Vector3 vtxPos3(0.2_mm, 0.2_mm, 10._mm);
0140
0141 std::vector<Vector3> vtxPosVec{vtxPos1, vtxPos2, vtxPos3};
0142
0143
0144 double resD0 = resIPDist(gen);
0145 double resZ0 = resIPDist(gen);
0146 double resPh = resAngDist(gen);
0147 double resTh = resAngDist(gen);
0148 double resQp = resQoPDist(gen);
0149
0150 std::vector<Vertex> vtxList;
0151 for (auto& vtxPos : vtxPosVec) {
0152 Vertex vtx(vtxPos);
0153
0154 SquareMatrix4 posCovariance(SquareMatrix4::Identity());
0155 vtx.setFullCovariance(posCovariance);
0156
0157 vtxList.push_back(vtx);
0158 }
0159
0160 std::vector<Vertex*> vtxPtrList;
0161 ACTS_DEBUG("All vertices in test case:");
0162 int cv = 0;
0163 for (auto& vtx : vtxList) {
0164 cv++;
0165 ACTS_DEBUG("\t" << cv << ". vertex ptr: " << &vtx);
0166 vtxPtrList.push_back(&vtx);
0167 }
0168
0169 std::vector<BoundTrackParameters> allTracks;
0170
0171 unsigned int nTracksPerVtx = 4;
0172
0173
0174 for (unsigned int iTrack = 0; iTrack < nTracksPerVtx * vtxPosVec.size();
0175 iTrack++) {
0176
0177 double q = qDist(gen) < 0 ? -1. : 1.;
0178
0179
0180 Covariance covMat;
0181
0182 covMat << resD0 * resD0, 0., 0., 0., 0., 0., 0., resZ0 * resZ0, 0., 0., 0.,
0183 0., 0., 0., resPh * resPh, 0., 0., 0., 0., 0., 0., resTh * resTh, 0.,
0184 0., 0., 0., 0., 0., resQp * resQp, 0., 0., 0., 0., 0., 0., 1.;
0185
0186
0187 int vtxIdx = static_cast<int>(iTrack / nTracksPerVtx);
0188
0189
0190 BoundTrackParameters::ParametersVector paramVec;
0191 paramVec << d0Dist(gen), z0Dist(gen), phiDist(gen), thetaDist(gen),
0192 q / pTDist(gen), 0.;
0193
0194 std::shared_ptr<PerigeeSurface> perigeeSurface =
0195 Surface::makeShared<PerigeeSurface>(vtxPosVec[vtxIdx]);
0196
0197 allTracks.emplace_back(perigeeSurface, paramVec, std::move(covMat),
0198 ParticleHypothesis::pion());
0199 }
0200
0201 int ct = 0;
0202 ACTS_DEBUG("All tracks in test case:");
0203 for (auto& trk : allTracks) {
0204 ct++;
0205 ACTS_DEBUG("\t" << ct << ". track ptr: " << &trk);
0206 }
0207
0208 AdaptiveMultiVertexFitter::State state(*bField, magFieldContext);
0209
0210 for (unsigned int iTrack = 0; iTrack < nTracksPerVtx * vtxPosVec.size();
0211 iTrack++) {
0212
0213 int vtxIdx = static_cast<int>(iTrack / nTracksPerVtx);
0214
0215 InputTrack inputTrack{&allTracks[iTrack]};
0216
0217 state.vtxInfoMap[&(vtxList[vtxIdx])].trackLinks.push_back(inputTrack);
0218 state.tracksAtVerticesMap.insert(
0219 std::make_pair(std::make_pair(inputTrack, &(vtxList[vtxIdx])),
0220 TrackAtVertex(1., allTracks[iTrack], inputTrack)));
0221
0222
0223
0224 if (iTrack == 0) {
0225 state.vtxInfoMap[&(vtxList.at(1))].trackLinks.push_back(inputTrack);
0226 state.tracksAtVerticesMap.insert(
0227 std::make_pair(std::make_pair(inputTrack, &(vtxList.at(1))),
0228 TrackAtVertex(1., allTracks[iTrack], inputTrack)));
0229 }
0230 }
0231
0232 for (auto& vtx : vtxPtrList) {
0233 state.addVertexToMultiMap(*vtx);
0234 ACTS_DEBUG("Vertex, with ptr: " << vtx);
0235 for (auto& trk : state.vtxInfoMap[vtx].trackLinks) {
0236 ACTS_DEBUG("\t track ptr: " << trk);
0237 }
0238 }
0239
0240 ACTS_DEBUG("Checking all vertices linked to a single track:");
0241 for (auto& trk : allTracks) {
0242 ACTS_DEBUG("Track with ptr: " << &trk);
0243 auto range = state.trackToVerticesMultiMap.equal_range(InputTrack{&trk});
0244 for (auto vtxIter = range.first; vtxIter != range.second; ++vtxIter) {
0245 ACTS_DEBUG("\t used by vertex: " << vtxIter->second);
0246 }
0247 }
0248
0249
0250
0251 std::vector<Vertex> seedListCopy = vtxList;
0252
0253 auto res1 = fitter.addVtxToFit(state, vtxList.at(0), vertexingOptions);
0254 ACTS_DEBUG("Tracks linked to each vertex AFTER fit:");
0255 int c = 0;
0256 for (auto& vtx : vtxPtrList) {
0257 c++;
0258 ACTS_DEBUG(c << ". vertex, with ptr: " << vtx);
0259 for (const auto& trk : state.vtxInfoMap[vtx].trackLinks) {
0260 ACTS_DEBUG("\t track ptr: " << trk);
0261 }
0262 }
0263
0264 ACTS_DEBUG("Checking all vertices linked to a single track AFTER fit:");
0265 for (auto& trk : allTracks) {
0266 ACTS_DEBUG("Track with ptr: " << &trk);
0267 auto range = state.trackToVerticesMultiMap.equal_range(InputTrack{&trk});
0268 for (auto vtxIter = range.first; vtxIter != range.second; ++vtxIter) {
0269 ACTS_DEBUG("\t used by vertex: " << vtxIter->second);
0270 }
0271 }
0272
0273 BOOST_CHECK(res1.ok());
0274
0275 ACTS_DEBUG("Vertex positions after fit of vertex 1 and 2:");
0276 for (std::size_t vtxIter = 0; vtxIter < 3; vtxIter++) {
0277 ACTS_DEBUG("Vtx " << vtxIter + 1 << ", seed position:\n "
0278 << seedListCopy.at(vtxIter).fullPosition()
0279 << "\nFitted position:\n "
0280 << vtxList.at(vtxIter).fullPosition());
0281 }
0282
0283
0284
0285 BOOST_CHECK_NE(vtxList.at(0).fullPosition(),
0286 seedListCopy.at(0).fullPosition());
0287 BOOST_CHECK_NE(vtxList.at(1).fullPosition(),
0288 seedListCopy.at(1).fullPosition());
0289 BOOST_CHECK_EQUAL(vtxList.at(2).fullPosition(),
0290 seedListCopy.at(2).fullPosition());
0291
0292 CHECK_CLOSE_ABS(vtxList.at(0).fullPosition(),
0293 seedListCopy.at(0).fullPosition(), 1_mm);
0294 CHECK_CLOSE_ABS(vtxList.at(1).fullPosition(),
0295 seedListCopy.at(1).fullPosition(), 1_mm);
0296
0297 auto res2 = fitter.addVtxToFit(state, vtxList.at(2), vertexingOptions);
0298 BOOST_CHECK(res2.ok());
0299
0300
0301 BOOST_CHECK_NE(vtxList.at(2).fullPosition(),
0302 seedListCopy.at(2).fullPosition());
0303 CHECK_CLOSE_ABS(vtxList.at(2).fullPosition(),
0304 seedListCopy.at(2).fullPosition(), 1_mm);
0305
0306 ACTS_DEBUG("Vertex positions after fit of vertex 3:");
0307 ACTS_DEBUG("Vtx 1, seed position:\n " << seedListCopy.at(0).fullPosition()
0308 << "\nFitted position:\n "
0309 << vtxList.at(0).fullPosition());
0310 ACTS_DEBUG("Vtx 2, seed position:\n " << seedListCopy.at(1).fullPosition()
0311 << "\nFitted position:\n "
0312 << vtxList.at(1).fullPosition());
0313 ACTS_DEBUG("Vtx 3, seed position:\n " << seedListCopy.at(2).fullPosition()
0314 << "\nFitted position:\n "
0315 << vtxList.at(2).fullPosition());
0316 }
0317
0318
0319
0320 BOOST_AUTO_TEST_CASE(time_fitting) {
0321
0322 int mySeed = 31415;
0323 std::mt19937 gen(mySeed);
0324
0325
0326 auto bField = std::make_shared<ConstantBField>(Vector3{0.0, 0.0, 1_T});
0327
0328
0329 EigenStepper<> stepper(bField);
0330
0331
0332 auto propagator = std::make_shared<Propagator>(stepper);
0333
0334 VertexingOptions vertexingOptions(geoContext, magFieldContext);
0335
0336 ImpactPointEstimator::Config ip3dEstCfg(bField, propagator);
0337 ImpactPointEstimator ip3dEst(ip3dEstCfg);
0338
0339 AdaptiveMultiVertexFitter::Config fitterCfg(ip3dEst);
0340
0341
0342 Linearizer::Config ltConfig;
0343 ltConfig.bField = bField;
0344 ltConfig.propagator = propagator;
0345 Linearizer linearizer(ltConfig);
0346
0347
0348 fitterCfg.doSmoothing = true;
0349
0350 fitterCfg.useTime = true;
0351 fitterCfg.extractParameters.connect<&InputTrack::extractParameters>();
0352 fitterCfg.trackLinearizer.connect<&Linearizer::linearizeTrack>(&linearizer);
0353
0354 AdaptiveMultiVertexFitter fitter(std::move(fitterCfg));
0355
0356
0357 double trueVtxTime = 40.0_ps;
0358 Vector3 trueVtxPos(-0.15_mm, -0.1_mm, -1.5_mm);
0359
0360
0361 Vector4 vtxSeedPos(0.0_mm, 0.0_mm, -1.4_mm, 0.0_ps);
0362
0363 Vertex vtx(vtxSeedPos);
0364
0365 SquareMatrix4 initialCovariance(SquareMatrix4::Identity() * 1e+8);
0366 vtx.setFullCovariance(initialCovariance);
0367
0368
0369 std::vector<BoundTrackParameters> trks;
0370
0371 unsigned int nTracks = 4;
0372 for (unsigned int _ = 0; _ < nTracks; _++) {
0373
0374 double q = qDist(gen) < 0 ? -1. : 1.;
0375
0376
0377 double resD0 = resIPDist(gen);
0378 double resZ0 = resIPDist(gen);
0379 double resPh = resAngDist(gen);
0380 double resTh = resAngDist(gen);
0381 double resQp = resQoPDist(gen);
0382 double resT = resTDist(gen);
0383
0384
0385 Covariance covMat;
0386
0387
0388 covMat <<
0389 resD0 * resD0, 0., 0., 0., 0., 0.,
0390 0., resZ0 * resZ0, 0., 0., 0., 0.,
0391 0., 0., resPh * resPh, 0., 0., 0.,
0392 0., 0., 0., resTh * resTh, 0., 0.,
0393 0., 0., 0., 0., resQp * resQp, 0.,
0394 0., 0., 0., 0., 0., resT * resT;
0395
0396
0397
0398 BoundTrackParameters::ParametersVector paramVec;
0399 paramVec << d0Dist(gen), z0Dist(gen), phiDist(gen), thetaDist(gen),
0400 q / pTDist(gen), trueVtxTime + relTDist(gen);
0401
0402 std::shared_ptr<PerigeeSurface> perigeeSurface =
0403 Surface::makeShared<PerigeeSurface>(trueVtxPos);
0404
0405 trks.emplace_back(perigeeSurface, paramVec, std::move(covMat),
0406 ParticleHypothesis::pion());
0407 }
0408
0409 std::vector<const BoundTrackParameters*> trksPtr;
0410 for (const auto& trk : trks) {
0411 trksPtr.push_back(&trk);
0412 }
0413
0414
0415 AdaptiveMultiVertexFitter::State state(*bField, magFieldContext);
0416
0417 for (const auto& trk : trks) {
0418 ACTS_DEBUG("Track parameters:\n" << trk);
0419
0420 state.vtxInfoMap[&vtx].trackLinks.push_back(InputTrack{&trk});
0421 state.tracksAtVerticesMap.insert(
0422 std::make_pair(std::make_pair(InputTrack{&trk}, &vtx),
0423 TrackAtVertex(1., trk, InputTrack{&trk})));
0424 }
0425
0426 state.addVertexToMultiMap(vtx);
0427
0428 auto res = fitter.addVtxToFit(state, vtx, vertexingOptions);
0429
0430 BOOST_CHECK(res.ok());
0431
0432 ACTS_DEBUG("Truth vertex position: " << trueVtxPos.transpose());
0433 ACTS_DEBUG("Fitted vertex position: " << vtx.position().transpose());
0434
0435 ACTS_DEBUG("Truth vertex time: " << trueVtxTime);
0436 ACTS_DEBUG("Fitted vertex time: " << vtx.time());
0437
0438
0439 CHECK_CLOSE_ABS(trueVtxPos, vtx.position(), 60_um);
0440 CHECK_CLOSE_ABS(trueVtxTime, vtx.time(), 2_ps);
0441
0442 const SquareMatrix4& vtxCov = vtx.fullCovariance();
0443
0444 ACTS_DEBUG("Vertex 4D covariance after the fit:\n" << vtxCov);
0445
0446
0447 for (std::size_t i = 0; i <= 3; i++) {
0448 BOOST_CHECK_GT(vtxCov(i, i), 0.);
0449 }
0450
0451
0452 CHECK_CLOSE_ABS(vtxCov - vtxCov.transpose(), SquareMatrix4::Zero(), 1e-5);
0453 }
0454
0455
0456
0457
0458 BOOST_AUTO_TEST_CASE(adaptive_multi_vertex_fitter_test_athena) {
0459
0460 auto bField = std::make_shared<ConstantBField>(Vector3{0.0, 0.0, 2_T});
0461
0462
0463
0464 EigenStepper<> stepper(bField);
0465
0466
0467 auto propagator = std::make_shared<Propagator>(stepper);
0468
0469 VertexingOptions vertexingOptions(geoContext, magFieldContext);
0470
0471 ImpactPointEstimator::Config ip3dEstCfg(bField, propagator);
0472 ImpactPointEstimator ip3dEst(ip3dEstCfg);
0473
0474 std::vector<double> temperatures(1, 3.);
0475 AnnealingUtility::Config annealingConfig;
0476 annealingConfig.setOfTemperatures = temperatures;
0477 AnnealingUtility annealingUtility(annealingConfig);
0478
0479 AdaptiveMultiVertexFitter::Config fitterCfg(ip3dEst);
0480
0481 fitterCfg.annealingTool = annealingUtility;
0482 fitterCfg.extractParameters.connect<&InputTrack::extractParameters>();
0483
0484
0485 Linearizer::Config ltConfig;
0486 ltConfig.bField = bField;
0487 ltConfig.propagator = propagator;
0488 Linearizer linearizer(ltConfig);
0489
0490 fitterCfg.trackLinearizer.connect<&Linearizer::linearizeTrack>(&linearizer);
0491
0492
0493
0494
0495 AdaptiveMultiVertexFitter fitter(std::move(fitterCfg));
0496
0497
0498 Vector3 pos1a(0.5_mm, -0.5_mm, 2.4_mm);
0499 Vector3 mom1a(1000_MeV, 0_MeV, -500_MeV);
0500 Vector3 pos1b(0.5_mm, -0.5_mm, 3.5_mm);
0501 Vector3 mom1b(0_MeV, 1000_MeV, 500_MeV);
0502 Vector3 pos1c(-0.2_mm, 0.1_mm, 3.4_mm);
0503 Vector3 mom1c(-50_MeV, 180_MeV, 300_MeV);
0504
0505 Vector3 pos1d(-0.1_mm, 0.3_mm, 3.0_mm);
0506 Vector3 mom1d(-80_MeV, 480_MeV, -100_MeV);
0507 Vector3 pos1e(-0.01_mm, 0.01_mm, 2.9_mm);
0508 Vector3 mom1e(-600_MeV, 10_MeV, 210_MeV);
0509
0510 Vector3 pos1f(-0.07_mm, 0.03_mm, 2.5_mm);
0511 Vector3 mom1f(240_MeV, 110_MeV, 150_MeV);
0512
0513
0514 Covariance covMat1;
0515 covMat1 << 1_mm * 1_mm, 0, 0., 0, 0., 0, 0, 1_mm * 1_mm, 0, 0., 0, 0, 0., 0,
0516 0.1, 0, 0, 0, 0, 0., 0, 0.1, 0, 0, 0., 0, 0, 0, 1. / (10_GeV * 10_GeV), 0,
0517 0, 0, 0, 0, 0, 1_ns;
0518
0519 std::vector<BoundTrackParameters> params1 = {
0520 BoundTrackParameters::create(Surface::makeShared<PerigeeSurface>(pos1a),
0521 geoContext, makeVector4(pos1a, 0),
0522 mom1a.normalized(), 1_e / mom1a.norm(),
0523 covMat1, ParticleHypothesis::pion())
0524 .value(),
0525 BoundTrackParameters::create(Surface::makeShared<PerigeeSurface>(pos1b),
0526 geoContext, makeVector4(pos1b, 0),
0527 mom1b.normalized(), -1_e / mom1b.norm(),
0528 covMat1, ParticleHypothesis::pion())
0529 .value(),
0530 BoundTrackParameters::create(Surface::makeShared<PerigeeSurface>(pos1c),
0531 geoContext, makeVector4(pos1c, 0),
0532 mom1c.normalized(), 1_e / mom1c.norm(),
0533 covMat1, ParticleHypothesis::pion())
0534 .value(),
0535 BoundTrackParameters::create(Surface::makeShared<PerigeeSurface>(pos1d),
0536 geoContext, makeVector4(pos1d, 0),
0537 mom1d.normalized(), -1_e / mom1d.norm(),
0538 covMat1, ParticleHypothesis::pion())
0539 .value(),
0540 BoundTrackParameters::create(Surface::makeShared<PerigeeSurface>(pos1e),
0541 geoContext, makeVector4(pos1e, 0),
0542 mom1e.normalized(), 1_e / mom1e.norm(),
0543 covMat1, ParticleHypothesis::pion())
0544 .value(),
0545 BoundTrackParameters::create(Surface::makeShared<PerigeeSurface>(pos1f),
0546 geoContext, makeVector4(pos1f, 0),
0547 mom1f.normalized(), -1_e / mom1f.norm(),
0548 covMat1, ParticleHypothesis::pion())
0549 .value(),
0550 };
0551
0552
0553 Vector3 pos2a(0.2_mm, 0_mm, -4.9_mm);
0554 Vector3 mom2a(5000_MeV, 30_MeV, 200_MeV);
0555 Vector3 pos2b(-0.5_mm, 0.1_mm, -5.1_mm);
0556 Vector3 mom2b(800_MeV, 1200_MeV, 200_MeV);
0557 Vector3 pos2c(0.05_mm, -0.5_mm, -4.7_mm);
0558 Vector3 mom2c(400_MeV, -300_MeV, -200_MeV);
0559
0560
0561 Covariance covMat2 = covMat1;
0562
0563 std::vector<BoundTrackParameters> params2 = {
0564 BoundTrackParameters::create(Surface::makeShared<PerigeeSurface>(pos2a),
0565 geoContext, makeVector4(pos2a, 0),
0566 mom2a.normalized(), 1_e / mom2a.norm(),
0567 covMat2, ParticleHypothesis::pion())
0568 .value(),
0569 BoundTrackParameters::create(Surface::makeShared<PerigeeSurface>(pos2b),
0570 geoContext, makeVector4(pos2b, 0),
0571 mom2b.normalized(), -1_e / mom2b.norm(),
0572 covMat2, ParticleHypothesis::pion())
0573 .value(),
0574 BoundTrackParameters::create(Surface::makeShared<PerigeeSurface>(pos2c),
0575 geoContext, makeVector4(pos2c, 0),
0576 mom2c.normalized(), -1_e / mom2c.norm(),
0577 covMat2, ParticleHypothesis::pion())
0578 .value(),
0579 };
0580
0581 AdaptiveMultiVertexFitter::State state(*bField, magFieldContext);
0582
0583
0584 SquareMatrix4 covConstr(SquareMatrix4::Identity());
0585 covConstr = covConstr * 1e+8;
0586 covConstr(3, 3) = 0.;
0587
0588
0589 Vector3 vtxPos1(0.15_mm, 0.15_mm, 2.9_mm);
0590 Vertex vtx1(vtxPos1);
0591
0592
0593 state.vertexCollection.push_back(&vtx1);
0594
0595
0596 Vertex vtx1Constr(vtxPos1);
0597 vtx1Constr.setFullCovariance(covConstr);
0598 vtx1Constr.setFitQuality(0, -3);
0599
0600
0601 VertexInfo vtxInfo1;
0602 vtxInfo1.seedPosition = vtxInfo1.linPoint;
0603 vtxInfo1.linPoint.setZero();
0604 vtxInfo1.linPoint.head<3>() = vtxPos1;
0605 vtxInfo1.constraint = std::move(vtx1Constr);
0606 vtxInfo1.oldPosition = vtxInfo1.linPoint;
0607
0608 for (const auto& trk : params1) {
0609 vtxInfo1.trackLinks.push_back(InputTrack{&trk});
0610 state.tracksAtVerticesMap.insert(
0611 std::make_pair(std::make_pair(InputTrack{&trk}, &vtx1),
0612 TrackAtVertex(1.5, trk, InputTrack{&trk})));
0613 }
0614
0615
0616 Vector3 vtxPos2(0.3_mm, -0.2_mm, -4.8_mm);
0617 Vertex vtx2(vtxPos2);
0618
0619
0620 state.vertexCollection.push_back(&vtx2);
0621
0622
0623 Vertex vtx2Constr(vtxPos2);
0624 vtx2Constr.setFullCovariance(covConstr);
0625 vtx2Constr.setFitQuality(0, -3);
0626
0627
0628 VertexInfo vtxInfo2;
0629 vtxInfo2.linPoint.setZero();
0630 vtxInfo2.linPoint.head<3>() = vtxPos2;
0631 vtxInfo2.constraint = std::move(vtx2Constr);
0632 vtxInfo2.oldPosition = vtxInfo2.linPoint;
0633 vtxInfo2.seedPosition = vtxInfo2.linPoint;
0634
0635 for (const auto& trk : params2) {
0636 vtxInfo2.trackLinks.push_back(InputTrack{&trk});
0637 state.tracksAtVerticesMap.insert(
0638 std::make_pair(std::make_pair(InputTrack{&trk}, &vtx2),
0639 TrackAtVertex(1.5, trk, InputTrack{&trk})));
0640 }
0641
0642 state.vtxInfoMap[&vtx1] = std::move(vtxInfo1);
0643 state.vtxInfoMap[&vtx2] = std::move(vtxInfo2);
0644
0645 state.addVertexToMultiMap(vtx1);
0646 state.addVertexToMultiMap(vtx2);
0647
0648
0649 fitter.fit(state, vertexingOptions);
0650
0651 auto vtx1Fitted = state.vertexCollection.at(0);
0652 auto vtx1PosFitted = vtx1Fitted->position();
0653 auto vtx1CovFitted = vtx1Fitted->covariance();
0654 auto trks1 = state.vtxInfoMap.at(vtx1Fitted).trackLinks;
0655 auto vtx1FQ = vtx1Fitted->fitQuality();
0656
0657 auto vtx2Fitted = state.vertexCollection.at(1);
0658 auto vtx2PosFitted = vtx2Fitted->position();
0659 auto vtx2CovFitted = vtx2Fitted->covariance();
0660 auto trks2 = state.vtxInfoMap.at(vtx2Fitted).trackLinks;
0661 auto vtx2FQ = vtx2Fitted->fitQuality();
0662
0663
0664 ACTS_DEBUG("Vertex 1, position: " << vtx1PosFitted);
0665 ACTS_DEBUG("Vertex 1, covariance: " << vtx1CovFitted);
0666 for (const auto& trk : trks1) {
0667 auto& trkAtVtx =
0668 state.tracksAtVerticesMap.at(std::make_pair(trk, vtx1Fitted));
0669 ACTS_DEBUG("\tTrack weight:" << trkAtVtx.trackWeight);
0670 }
0671 ACTS_DEBUG("Vertex 1, chi2: " << vtx1FQ.first);
0672 ACTS_DEBUG("Vertex 1, ndf: " << vtx1FQ.second);
0673
0674
0675 ACTS_DEBUG("Vertex 2, position: " << vtx2PosFitted);
0676 ACTS_DEBUG("Vertex 2, covariance: " << vtx2CovFitted);
0677 for (const auto& trk : trks2) {
0678 auto& trkAtVtx =
0679 state.tracksAtVerticesMap.at(std::make_pair(trk, vtx2Fitted));
0680 ACTS_DEBUG("\tTrack weight:" << trkAtVtx.trackWeight);
0681 }
0682 ACTS_DEBUG("Vertex 2, chi2: " << vtx2FQ.first);
0683 ACTS_DEBUG("Vertex 2, ndf: " << vtx2FQ.second);
0684
0685
0686
0687 const Vector3 expVtx1Pos(0.077_mm, -0.189_mm, 2.924_mm);
0688
0689
0690 SquareMatrix3 expVtx1Cov;
0691 expVtx1Cov << 0.329, 0.016, -0.035, 0.016, 0.250, 0.085, -0.035, 0.085, 0.242;
0692
0693 ActsVector<6> expVtx1TrkWeights;
0694 expVtx1TrkWeights << 0.8128, 0.7994, 0.8164, 0.8165, 0.8165, 0.8119;
0695 const double expVtx1chi2 = 0.9812;
0696 const double expVtx1ndf = 6.7474;
0697
0698
0699 const Vector3 expVtx2Pos(-0.443_mm, -0.044_mm, -4.829_mm);
0700
0701 SquareMatrix3 expVtx2Cov;
0702 expVtx2Cov << 1.088, 0.028, -0.066, 0.028, 0.643, 0.073, -0.066, 0.073, 0.435;
0703
0704 const Vector3 expVtx2TrkWeights(0.8172, 0.8150, 0.8137);
0705 const double expVtx2chi2 = 0.2114;
0706 const double expVtx2ndf = 1.8920;
0707
0708
0709
0710 CHECK_CLOSE_ABS(vtx1PosFitted, expVtx1Pos, 0.001_mm);
0711 CHECK_CLOSE_ABS(vtx1CovFitted, expVtx1Cov, 0.001_mm);
0712 int trkCount = 0;
0713 for (const auto& trk : trks1) {
0714 auto& trkAtVtx =
0715 state.tracksAtVerticesMap.at(std::make_pair(trk, vtx1Fitted));
0716 CHECK_CLOSE_ABS(trkAtVtx.trackWeight, expVtx1TrkWeights[trkCount], 0.001);
0717 trkCount++;
0718 }
0719 CHECK_CLOSE_ABS(vtx1FQ.first, expVtx1chi2, 0.001);
0720 CHECK_CLOSE_ABS(vtx1FQ.second, expVtx1ndf, 0.001);
0721
0722
0723 CHECK_CLOSE_ABS(vtx2PosFitted, expVtx2Pos, 0.001_mm);
0724 CHECK_CLOSE_ABS(vtx2CovFitted, expVtx2Cov, 0.001_mm);
0725 trkCount = 0;
0726 for (const auto& trk : trks2) {
0727 auto& trkAtVtx =
0728 state.tracksAtVerticesMap.at(std::make_pair(trk, vtx2Fitted));
0729 CHECK_CLOSE_ABS(trkAtVtx.trackWeight, expVtx2TrkWeights[trkCount], 0.001);
0730 trkCount++;
0731 }
0732 CHECK_CLOSE_ABS(vtx2FQ.first, expVtx2chi2, 0.001);
0733 CHECK_CLOSE_ABS(vtx2FQ.second, expVtx2ndf, 0.001);
0734 }
0735
0736 }