File indexing completed on 2025-08-05 08:09:51
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/Vertexing/AdaptiveMultiVertexFinderAlgorithm.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Units.hpp"
0013 #include "Acts/EventData/GenericBoundTrackParameters.hpp"
0014 #include "Acts/Propagator/EigenStepper.hpp"
0015 #include "Acts/Utilities/AnnealingUtility.hpp"
0016 #include "Acts/Utilities/Logger.hpp"
0017 #include "Acts/Utilities/Result.hpp"
0018 #include "Acts/Vertexing/AdaptiveGridTrackDensity.hpp"
0019 #include "Acts/Vertexing/AdaptiveMultiVertexFinder.hpp"
0020 #include "Acts/Vertexing/AdaptiveMultiVertexFitter.hpp"
0021 #include "Acts/Vertexing/GaussianTrackDensity.hpp"
0022 #include "Acts/Vertexing/ImpactPointEstimator.hpp"
0023 #include "Acts/Vertexing/TrackAtVertex.hpp"
0024 #include "Acts/Vertexing/TrackDensityVertexFinder.hpp"
0025 #include "Acts/Vertexing/Vertex.hpp"
0026 #include "Acts/Vertexing/VertexingOptions.hpp"
0027 #include "ActsExamples/EventData/ProtoVertex.hpp"
0028 #include "ActsExamples/Framework/AlgorithmContext.hpp"
0029 #include "ActsExamples/Framework/ProcessCode.hpp"
0030
0031 #include <memory>
0032 #include <optional>
0033 #include <ostream>
0034 #include <stdexcept>
0035 #include <system_error>
0036
0037 #include "VertexingHelpers.hpp"
0038
0039 ActsExamples::AdaptiveMultiVertexFinderAlgorithm::
0040 AdaptiveMultiVertexFinderAlgorithm(const Config& config,
0041 Acts::Logging::Level level)
0042 : ActsExamples::IAlgorithm("AdaptiveMultiVertexFinder", level),
0043 m_cfg(config),
0044 m_propagator{[&]() {
0045
0046 Acts::EigenStepper<> stepper(m_cfg.bField);
0047
0048
0049 return std::make_shared<Propagator>(stepper);
0050 }()},
0051 m_ipEstimator{[&]() {
0052
0053 Acts::ImpactPointEstimator::Config ipEstimatorCfg(m_cfg.bField,
0054 m_propagator);
0055 return Acts::ImpactPointEstimator(
0056 ipEstimatorCfg, logger().cloneWithSuffix("ImpactPointEstimator"));
0057 }()},
0058 m_linearizer{[&] {
0059
0060 Linearizer::Config ltConfig;
0061 ltConfig.bField = m_cfg.bField;
0062 ltConfig.propagator = m_propagator;
0063 return Linearizer(ltConfig,
0064 logger().cloneWithSuffix("HelicalTrackLinearizer"));
0065 }()},
0066 m_vertexFinder{makeVertexFinder()} {
0067 if (m_cfg.inputTrackParameters.empty()) {
0068 throw std::invalid_argument("Missing input track parameter collection");
0069 }
0070 if (m_cfg.outputProtoVertices.empty()) {
0071 throw std::invalid_argument("Missing output proto vertices collection");
0072 }
0073 if (m_cfg.outputVertices.empty()) {
0074 throw std::invalid_argument("Missing output vertices collection");
0075 }
0076
0077 m_inputTrackParameters.initialize(m_cfg.inputTrackParameters);
0078 m_outputProtoVertices.initialize(m_cfg.outputProtoVertices);
0079 m_outputVertices.initialize(m_cfg.outputVertices);
0080 }
0081
0082 auto ActsExamples::AdaptiveMultiVertexFinderAlgorithm::makeVertexFinder() const
0083 -> Acts::AdaptiveMultiVertexFinder {
0084 std::shared_ptr<const Acts::IVertexFinder> seedFinder;
0085 if (m_cfg.seedFinder == SeedFinder::GaussianSeeder) {
0086 using Seeder = Acts::TrackDensityVertexFinder;
0087 Acts::GaussianTrackDensity::Config trkDensityCfg;
0088 trkDensityCfg.extractParameters
0089 .connect<&Acts::InputTrack::extractParameters>();
0090 seedFinder = std::make_shared<Seeder>(Seeder::Config{trkDensityCfg});
0091 } else if (m_cfg.seedFinder == SeedFinder::AdaptiveGridSeeder) {
0092
0093 Acts::AdaptiveGridTrackDensity::Config trkDensityCfg;
0094
0095 trkDensityCfg.spatialBinExtent = 15. * Acts::UnitConstants::um;
0096
0097 trkDensityCfg.temporalBinExtent = 19. * Acts::UnitConstants::mm;
0098 trkDensityCfg.useTime = m_cfg.useTime;
0099 Acts::AdaptiveGridTrackDensity trkDensity(trkDensityCfg);
0100
0101
0102 using Seeder = Acts::AdaptiveGridDensityVertexFinder;
0103 Seeder::Config seederConfig(trkDensity);
0104 seederConfig.extractParameters
0105 .connect<&Acts::InputTrack::extractParameters>();
0106 seedFinder = std::make_shared<Seeder>(seederConfig);
0107 } else {
0108 throw std::invalid_argument("Unknown seed finder");
0109 }
0110
0111
0112 Acts::AnnealingUtility::Config annealingConfig;
0113 annealingConfig.setOfTemperatures = {1.};
0114 Acts::AnnealingUtility annealingUtility(annealingConfig);
0115
0116
0117 Fitter::Config fitterCfg(m_ipEstimator);
0118 fitterCfg.annealingTool = annealingUtility;
0119 fitterCfg.minWeight = 0.001;
0120 fitterCfg.doSmoothing = true;
0121 fitterCfg.useTime = m_cfg.useTime;
0122 fitterCfg.extractParameters.connect<&Acts::InputTrack::extractParameters>();
0123 fitterCfg.trackLinearizer.connect<&Linearizer::linearizeTrack>(&m_linearizer);
0124 Fitter fitter(std::move(fitterCfg),
0125 logger().cloneWithSuffix("AdaptiveMultiVertexFitter"));
0126
0127 Acts::AdaptiveMultiVertexFinder::Config finderConfig(
0128 std::move(fitter), seedFinder, m_ipEstimator, m_cfg.bField);
0129
0130
0131
0132 finderConfig.initialVariances << 1e+2, 1e+2, 1e+2, 1e+8;
0133 finderConfig.tracksMaxZinterval = 1. * Acts::UnitConstants::mm;
0134 finderConfig.maxIterations = 200;
0135 finderConfig.useTime = m_cfg.useTime;
0136
0137 finderConfig.tracksMaxSignificance = 5;
0138
0139 finderConfig.doFullSplitting = false;
0140
0141 finderConfig.maxMergeVertexSignificance = 3;
0142 if (m_cfg.useTime) {
0143
0144
0145
0146
0147
0148 finderConfig.tracksMaxSignificance = 6.7;
0149
0150
0151 finderConfig.maxMergeVertexSignificance = 5;
0152 }
0153 finderConfig.extractParameters
0154 .template connect<&Acts::InputTrack::extractParameters>();
0155
0156
0157 return Acts::AdaptiveMultiVertexFinder(std::move(finderConfig),
0158 logger().clone());
0159 }
0160
0161 ActsExamples::ProcessCode
0162 ActsExamples::AdaptiveMultiVertexFinderAlgorithm::execute(
0163 const ActsExamples::AlgorithmContext& ctx) const {
0164
0165
0166 const auto& inputTrackParameters = m_inputTrackParameters(ctx);
0167
0168 auto inputTracks = makeInputTracks(inputTrackParameters);
0169
0170 if (inputTrackParameters.size() != inputTracks.size()) {
0171 ACTS_ERROR("Input track containers do not align: "
0172 << inputTrackParameters.size() << " != " << inputTracks.size());
0173 }
0174
0175 for (const auto& trk : inputTrackParameters) {
0176 if (trk.covariance() && trk.covariance()->determinant() <= 0) {
0177
0178
0179 ACTS_WARNING("input track " << trk << " has det(cov) = "
0180 << trk.covariance()->determinant());
0181 }
0182 }
0183
0184
0185
0186
0187
0188
0189 auto state = m_vertexFinder.makeState(ctx.magFieldContext);
0190
0191
0192 Options finderOpts(ctx.geoContext, ctx.magFieldContext);
0193
0194 VertexCollection vertices;
0195
0196 if (inputTrackParameters.empty()) {
0197 ACTS_DEBUG("Empty track parameter collection found, skipping vertexing");
0198 } else {
0199 ACTS_DEBUG("Have " << inputTrackParameters.size()
0200 << " input track parameters, running vertexing");
0201
0202 auto result = m_vertexFinder.find(inputTracks, finderOpts, state);
0203
0204 if (result.ok()) {
0205 vertices = std::move(result.value());
0206 } else {
0207 ACTS_ERROR("Error in vertex finder: " << result.error().message());
0208 }
0209 }
0210
0211
0212 ACTS_INFO("Found " << vertices.size() << " vertices in event");
0213 for (const auto& vtx : vertices) {
0214 ACTS_DEBUG("Found vertex at " << vtx.fullPosition().transpose() << " with "
0215 << vtx.tracks().size() << " tracks.");
0216 }
0217
0218
0219 m_outputProtoVertices(ctx, makeProtoVertices(inputTracks, vertices));
0220
0221
0222 m_outputVertices(ctx, std::move(vertices));
0223
0224 return ActsExamples::ProcessCode::SUCCESS;
0225 }