File indexing completed on 2026-09-22 07:59:37
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/Vertexing/VertexFitterAlgorithm.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Propagator/Propagator.hpp"
0013 #include "Acts/Propagator/SympyStepper.hpp"
0014 #include "Acts/Vertexing/FullBilloirVertexFitter.hpp"
0015 #include "Acts/Vertexing/HelicalTrackLinearizer.hpp"
0016 #include "Acts/Vertexing/TrackAtVertex.hpp"
0017 #include "Acts/Vertexing/Vertex.hpp"
0018 #include "ActsExamples/EventData/Vertex.hpp"
0019 #include "ActsExamples/Framework/AlgorithmContext.hpp"
0020
0021 #include <ostream>
0022 #include <stdexcept>
0023
0024 namespace ActsExamples {
0025
0026 VertexFitterAlgorithm::VertexFitterAlgorithm(
0027 const Config& cfg, std::unique_ptr<const Acts::Logger> logger)
0028 : IAlgorithm("VertexFit", std::move(logger)), m_cfg(cfg) {
0029 if (m_cfg.inputTrackParameters.empty()) {
0030 throw std::invalid_argument("Missing input track parameter collection");
0031 }
0032 if (m_cfg.inputProtoVertices.empty()) {
0033 throw std::invalid_argument("Missing input proto vertices collection");
0034 }
0035
0036 m_inputTrackParameters.initialize(m_cfg.inputTrackParameters);
0037 m_inputProtoVertices.initialize(m_cfg.inputProtoVertices);
0038 m_outputVertices.initialize(m_cfg.outputVertices);
0039 }
0040
0041 ProcessCode VertexFitterAlgorithm::execute(const AlgorithmContext& ctx) const {
0042 using Propagator = Acts::Propagator<Acts::SympyStepper>;
0043 using PropagatorOptions = Propagator::Options<>;
0044 using Linearizer = Acts::HelicalTrackLinearizer;
0045 using VertexFitter = Acts::FullBilloirVertexFitter;
0046 using VertexFitterOptions = Acts::VertexingOptions;
0047
0048
0049 Acts::SympyStepper stepper(m_cfg.bField);
0050
0051
0052 auto propagator = std::make_shared<Propagator>(
0053 stepper, Acts::VoidNavigator{}, logger().cloneWithSuffix("Prop"));
0054
0055
0056 Linearizer::Config ltConfig;
0057 ltConfig.bField = m_cfg.bField;
0058 ltConfig.propagator = propagator;
0059 Linearizer linearizer(ltConfig, logger().cloneWithSuffix("HelLin"));
0060
0061 PropagatorOptions propagatorOpts(ctx.recoGeoContext, ctx.magFieldContext);
0062
0063 VertexFitter::Config vertexFitterCfg;
0064 vertexFitterCfg.extractParameters
0065 .connect<&Acts::InputTrack::extractParameters>();
0066 vertexFitterCfg.trackLinearizer.connect<&Linearizer::linearizeTrack>(
0067 &linearizer);
0068 VertexFitter vertexFitter(vertexFitterCfg);
0069 auto fieldCache = m_cfg.bField->makeCache(ctx.magFieldContext);
0070
0071 ACTS_VERBOSE("Read from '" << m_cfg.inputTrackParameters << "'");
0072 ACTS_VERBOSE("Read from '" << m_cfg.inputProtoVertices << "'");
0073
0074 const auto& inputTrackParameters = m_inputTrackParameters(ctx);
0075 ACTS_VERBOSE("Have " << inputTrackParameters.size() << " track parameters");
0076 const auto& protoVertices = m_inputProtoVertices(ctx);
0077 ACTS_VERBOSE("Have " << protoVertices.size() << " proto vertices");
0078
0079 std::vector<Acts::InputTrack> inputTracks;
0080
0081 VertexContainer fittedVertices;
0082
0083 for (const auto& protoVertex : protoVertices) {
0084
0085 if ((!m_cfg.doConstrainedFit) && (protoVertex.size() < 2)) {
0086 ACTS_INFO(
0087 "Skip un-constrained vertex fit on proto-vertex with less than two "
0088 "tracks");
0089 continue;
0090 }
0091
0092
0093 inputTracks.clear();
0094 inputTracks.reserve(protoVertex.size());
0095 for (const auto& trackIdx : protoVertex) {
0096 if (trackIdx >= inputTrackParameters.size()) {
0097 ACTS_ERROR("track parameters " << trackIdx << " does not exist");
0098 continue;
0099 }
0100
0101 inputTracks.emplace_back(&inputTrackParameters[trackIdx]);
0102 }
0103
0104 if (!m_cfg.doConstrainedFit) {
0105 VertexFitterOptions vfOptions(ctx.recoGeoContext, ctx.magFieldContext);
0106
0107 auto fitRes = vertexFitter.fit(inputTracks, vfOptions, fieldCache);
0108 if (fitRes.ok()) {
0109 fittedVertices.push_back(*fitRes);
0110 } else {
0111 ACTS_ERROR("Error in vertex fitter: " << fitRes.error().message());
0112 }
0113 } else {
0114
0115 Acts::Vertex theConstraint;
0116
0117 theConstraint.setFullCovariance(m_cfg.constraintCov);
0118 theConstraint.setFullPosition(m_cfg.constraintPos);
0119
0120
0121 VertexFitterOptions vfOptionsConstr(ctx.recoGeoContext,
0122 ctx.magFieldContext, theConstraint);
0123
0124 auto fitRes = vertexFitter.fit(inputTracks, vfOptionsConstr, fieldCache);
0125 if (fitRes.ok()) {
0126 fittedVertices.push_back(*fitRes);
0127 } else {
0128 ACTS_ERROR(
0129 "Error in constrained vertex fitter: " << fitRes.error().message());
0130 }
0131 }
0132
0133 if (fittedVertices.empty()) {
0134 ACTS_DEBUG("No fitted vertex");
0135 } else {
0136 ACTS_DEBUG("Fitted Vertex "
0137 << fittedVertices.back().fullPosition().transpose());
0138 ACTS_DEBUG(
0139 "Tracks at fitted Vertex: " << fittedVertices.back().tracks().size());
0140 }
0141 }
0142
0143 m_outputVertices(ctx, std::move(fittedVertices));
0144 return ProcessCode::SUCCESS;
0145 }
0146
0147 }