File indexing completed on 2024-09-27 07:03:01
0001
0002
0003
0004 #include "CKFTracking.h"
0005
0006 #include <Acts/Definitions/Algebra.hpp>
0007 #include <Acts/Definitions/TrackParametrization.hpp>
0008 #include <Acts/Definitions/Units.hpp>
0009 #include <Acts/EventData/GenericBoundTrackParameters.hpp>
0010 #if Acts_VERSION_MAJOR < 36
0011 #include <Acts/EventData/Measurement.hpp>
0012 #endif
0013 #include <Acts/EventData/MultiTrajectory.hpp>
0014 #include <Acts/EventData/ParticleHypothesis.hpp>
0015 #if Acts_VERSION_MAJOR >= 32
0016 #include "Acts/EventData/ProxyAccessor.hpp"
0017 #endif
0018 #include <Acts/EventData/SourceLink.hpp>
0019 #include <Acts/EventData/TrackContainer.hpp>
0020 #include <Acts/EventData/TrackProxy.hpp>
0021 #include <Acts/EventData/VectorMultiTrajectory.hpp>
0022 #include <Acts/EventData/VectorTrackContainer.hpp>
0023 #include <Acts/Geometry/GeometryIdentifier.hpp>
0024 #if Acts_VERSION_MAJOR >= 34
0025 #include "Acts/Propagator/AbortList.hpp"
0026 #include "Acts/Propagator/EigenStepper.hpp"
0027 #include "Acts/Propagator/MaterialInteractor.hpp"
0028 #include "Acts/Propagator/Navigator.hpp"
0029 #endif
0030 #include <Acts/Propagator/Propagator.hpp>
0031 #if Acts_VERSION_MAJOR >= 34
0032 #include "Acts/Propagator/StandardAborters.hpp"
0033 #endif
0034 #include <Acts/Surfaces/PerigeeSurface.hpp>
0035 #include <Acts/Surfaces/Surface.hpp>
0036 #include <Acts/TrackFitting/GainMatrixSmoother.hpp>
0037 #include <Acts/TrackFitting/GainMatrixUpdater.hpp>
0038 #include <Acts/Utilities/Logger.hpp>
0039 #if Acts_VERSION_MAJOR >= 34
0040 #include "Acts/Utilities/TrackHelpers.hpp"
0041 #endif
0042 #include <ActsExamples/EventData/IndexSourceLink.hpp>
0043 #include <ActsExamples/EventData/Measurement.hpp>
0044 #include <ActsExamples/EventData/MeasurementCalibration.hpp>
0045 #include <ActsExamples/EventData/Track.hpp>
0046 #include <edm4eic/Cov3f.h>
0047 #include <edm4eic/Cov6f.h>
0048 #include <edm4eic/Measurement2DCollection.h>
0049 #include <edm4eic/TrackParametersCollection.h>
0050 #include <edm4hep/Vector2f.h>
0051 #include <fmt/core.h>
0052 #include <Eigen/Core>
0053 #include <array>
0054 #include <cmath>
0055 #include <cstddef>
0056 #include <functional>
0057 #include <list>
0058 #include <optional>
0059 #include <utility>
0060
0061 #include "ActsGeometryProvider.h"
0062 #include "DD4hepBField.h"
0063 #include "extensions/spdlog/SpdlogFormatters.h" // IWYU pragma: keep
0064 #include "extensions/spdlog/SpdlogToActs.h"
0065
0066 namespace eicrecon {
0067
0068 using namespace Acts::UnitLiterals;
0069
0070
0071
0072
0073
0074
0075
0076 static constexpr std::array<std::pair<Acts::BoundIndices, double>, 6> edm4eic_indexed_units{{
0077 {Acts::eBoundLoc0, Acts::UnitConstants::mm},
0078 {Acts::eBoundLoc1, Acts::UnitConstants::mm},
0079 {Acts::eBoundPhi, 1.},
0080 {Acts::eBoundTheta, 1.},
0081 {Acts::eBoundQOverP, 1. / Acts::UnitConstants::GeV},
0082 {Acts::eBoundTime, Acts::UnitConstants::ns}
0083 }};
0084
0085 CKFTracking::CKFTracking() {
0086 }
0087
0088 void CKFTracking::init(std::shared_ptr<const ActsGeometryProvider> geo_svc, std::shared_ptr<spdlog::logger> log) {
0089 m_log = log;
0090 m_acts_logger = eicrecon::getSpdlogLogger("CKF", m_log);
0091
0092 m_geoSvc = geo_svc;
0093
0094 m_BField = std::dynamic_pointer_cast<const eicrecon::BField::DD4hepBField>(m_geoSvc->getFieldProvider());
0095 m_fieldctx = eicrecon::BField::BFieldVariant(m_BField);
0096
0097
0098 m_sourcelinkSelectorCfg = {
0099 {Acts::GeometryIdentifier(),
0100 {m_cfg.etaBins, m_cfg.chi2CutOff,
0101 {m_cfg.numMeasurementsCutOff.begin(), m_cfg.numMeasurementsCutOff.end()}
0102 }
0103 },
0104 };
0105 m_trackFinderFunc = CKFTracking::makeCKFTrackingFunction(m_geoSvc->trackingGeometry(), m_BField, logger());
0106 }
0107
0108 std::tuple<
0109 std::vector<ActsExamples::Trajectories*>,
0110 std::vector<ActsExamples::ConstTrackContainer*>
0111 >
0112 CKFTracking::process(const edm4eic::Measurement2DCollection& meas2Ds,
0113 const edm4eic::TrackParametersCollection &init_trk_params) {
0114
0115
0116
0117 auto measurements = std::make_shared<ActsExamples::MeasurementContainer>();
0118
0119
0120 std::list<ActsExamples::IndexSourceLink> sourceLinkStorage;
0121 ActsExamples::IndexSourceLinkContainer src_links;
0122 src_links.reserve(meas2Ds.size());
0123 std::size_t hit_index = 0;
0124
0125
0126 for (const auto& meas2D : meas2Ds) {
0127
0128
0129 sourceLinkStorage.emplace_back(meas2D.getSurface(), hit_index);
0130 ActsExamples::IndexSourceLink& sourceLink = sourceLinkStorage.back();
0131
0132
0133
0134
0135 src_links.insert(src_links.end(), sourceLink);
0136
0137
0138 Acts::Vector2 loc = Acts::Vector2::Zero();
0139 loc[Acts::eBoundLoc0] = meas2D.getLoc().a;
0140 loc[Acts::eBoundLoc1] = meas2D.getLoc().b;
0141
0142
0143 Acts::SquareMatrix2 cov = Acts::SquareMatrix2::Zero();
0144 cov(0, 0) = meas2D.getCovariance().xx;
0145 cov(1, 1) = meas2D.getCovariance().yy;
0146 cov(0, 1) = meas2D.getCovariance().xy;
0147 cov(1, 0) = meas2D.getCovariance().xy;
0148
0149 #if Acts_VERSION_MAJOR >= 36
0150 auto measurement = ActsExamples::makeFixedSizeMeasurement(
0151 Acts::SourceLink{sourceLink}, loc, cov, Acts::eBoundLoc0, Acts::eBoundLoc1);
0152 #else
0153 auto measurement = Acts::makeMeasurement(
0154 Acts::SourceLink{sourceLink}, loc, cov, Acts::eBoundLoc0, Acts::eBoundLoc1);
0155 #endif
0156 measurements->emplace_back(std::move(measurement));
0157
0158 hit_index++;
0159 }
0160
0161 ActsExamples::TrackParametersContainer acts_init_trk_params;
0162 for (const auto& track_parameter: init_trk_params) {
0163
0164 Acts::BoundVector params;
0165 params(Acts::eBoundLoc0) = track_parameter.getLoc().a * Acts::UnitConstants::mm;
0166 params(Acts::eBoundLoc1) = track_parameter.getLoc().b * Acts::UnitConstants::mm;
0167 params(Acts::eBoundPhi) = track_parameter.getPhi();
0168 params(Acts::eBoundTheta) = track_parameter.getTheta();
0169 params(Acts::eBoundQOverP) = track_parameter.getQOverP() / Acts::UnitConstants::GeV;
0170 params(Acts::eBoundTime) = track_parameter.getTime() * Acts::UnitConstants::ns;
0171
0172 double charge = std::copysign(1., track_parameter.getQOverP());
0173
0174 Acts::BoundSquareMatrix cov = Acts::BoundSquareMatrix::Zero();
0175 for (size_t i = 0; const auto& [a, x] : edm4eic_indexed_units) {
0176 for (size_t j = 0; const auto& [b, y] : edm4eic_indexed_units) {
0177 cov(a, b) = track_parameter.getCovariance()(i,j) * x * y;
0178 ++j;
0179 }
0180 ++i;
0181 }
0182
0183
0184 auto pSurface = Acts::Surface::makeShared<const Acts::PerigeeSurface>(Acts::Vector3(0,0,0));
0185
0186
0187 acts_init_trk_params.emplace_back(pSurface, params, cov, Acts::ParticleHypothesis::pion());
0188 }
0189
0190
0191 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3{0., 0., 0.});
0192
0193 ACTS_LOCAL_LOGGER(eicrecon::getSpdlogLogger("CKF", m_log, {"^No tracks found$"}));
0194
0195 Acts::PropagatorPlainOptions pOptions;
0196 pOptions.maxSteps = 10000;
0197
0198 ActsExamples::PassThroughCalibrator pcalibrator;
0199 ActsExamples::MeasurementCalibratorAdapter calibrator(pcalibrator, *measurements);
0200 Acts::GainMatrixUpdater kfUpdater;
0201 #if Acts_VERSION_MAJOR < 34
0202 Acts::GainMatrixSmoother kfSmoother;
0203 #endif
0204 Acts::MeasurementSelector measSel{m_sourcelinkSelectorCfg};
0205
0206 Acts::CombinatorialKalmanFilterExtensions<Acts::VectorMultiTrajectory>
0207 extensions;
0208 extensions.calibrator.connect<&ActsExamples::MeasurementCalibratorAdapter::calibrate>(
0209 &calibrator);
0210 extensions.updater.connect<
0211 &Acts::GainMatrixUpdater::operator()<Acts::VectorMultiTrajectory>>(
0212 &kfUpdater);
0213 #if Acts_VERSION_MAJOR < 34
0214 extensions.smoother.connect<
0215 &Acts::GainMatrixSmoother::operator()<Acts::VectorMultiTrajectory>>(
0216 &kfSmoother);
0217 #endif
0218 extensions.measurementSelector.connect<
0219 &Acts::MeasurementSelector::select<Acts::VectorMultiTrajectory>>(
0220 &measSel);
0221
0222 ActsExamples::IndexSourceLinkAccessor slAccessor;
0223 slAccessor.container = &src_links;
0224 Acts::SourceLinkAccessorDelegate<ActsExamples::IndexSourceLinkAccessor::Iterator>
0225 slAccessorDelegate;
0226 slAccessorDelegate.connect<&ActsExamples::IndexSourceLinkAccessor::range>(&slAccessor);
0227
0228
0229 #if Acts_VERSION_MAJOR < 34
0230 CKFTracking::TrackFinderOptions options(
0231 m_geoctx, m_fieldctx, m_calibctx, slAccessorDelegate,
0232 extensions, pOptions, &(*pSurface));
0233 #else
0234 CKFTracking::TrackFinderOptions options(
0235 m_geoctx, m_fieldctx, m_calibctx, slAccessorDelegate,
0236 extensions, pOptions);
0237 #endif
0238
0239 #if Acts_VERSION_MAJOR >= 34
0240 Acts::Propagator<Acts::EigenStepper<>, Acts::Navigator> extrapolator(
0241 Acts::EigenStepper<>(m_BField),
0242 Acts::Navigator({m_geoSvc->trackingGeometry()},
0243 logger().cloneWithSuffix("Navigator")),
0244 logger().cloneWithSuffix("Propagator"));
0245
0246 Acts::PropagatorOptions<Acts::ActionList<Acts::MaterialInteractor>,
0247 Acts::AbortList<Acts::EndOfWorldReached>>
0248 extrapolationOptions(m_geoctx, m_fieldctx);
0249 #endif
0250
0251
0252 auto trackContainer = std::make_shared<Acts::VectorTrackContainer>();
0253 auto trackStateContainer = std::make_shared<Acts::VectorMultiTrajectory>();
0254 ActsExamples::TrackContainer acts_tracks(trackContainer, trackStateContainer);
0255
0256
0257 acts_tracks.addColumn<unsigned int>("seed");
0258 #if Acts_VERSION_MAJOR >= 32
0259 Acts::ProxyAccessor<unsigned int> seedNumber("seed");
0260 #else
0261 Acts::TrackAccessor<unsigned int> seedNumber("seed");
0262 #endif
0263
0264
0265 for (std::size_t iseed = 0; iseed < acts_init_trk_params.size(); ++iseed) {
0266 auto result =
0267 (*m_trackFinderFunc)(acts_init_trk_params.at(iseed), options, acts_tracks);
0268
0269 if (!result.ok()) {
0270 m_log->debug("Track finding failed for seed {} with error {}", iseed, result.error());
0271 continue;
0272 }
0273
0274
0275 auto& tracksForSeed = result.value();
0276 for (auto& track : tracksForSeed) {
0277
0278 #if Acts_VERSION_MAJOR >=34
0279 auto smoothingResult = Acts::smoothTrack(m_geoctx, track, logger());
0280 if (!smoothingResult.ok()) {
0281 ACTS_ERROR("Smoothing for seed "
0282 << iseed << " and track " << track.index()
0283 << " failed with error " << smoothingResult.error());
0284 continue;
0285 }
0286
0287 auto extrapolationResult = Acts::extrapolateTrackToReferenceSurface(
0288 track, *pSurface, extrapolator, extrapolationOptions,
0289 Acts::TrackExtrapolationStrategy::firstOrLast, logger());
0290 if (!extrapolationResult.ok()) {
0291 ACTS_ERROR("Extrapolation for seed "
0292 << iseed << " and track " << track.index()
0293 << " failed with error " << extrapolationResult.error());
0294 continue;
0295 }
0296 #endif
0297
0298 seedNumber(track) = iseed;
0299 }
0300 }
0301
0302
0303
0304
0305
0306 auto constTrackStateContainer =
0307 std::make_shared<Acts::ConstVectorMultiTrajectory>(
0308 std::move(*trackStateContainer));
0309
0310 auto constTrackContainer =
0311 std::make_shared<Acts::ConstVectorTrackContainer>(
0312 std::move(*trackContainer));
0313
0314
0315
0316 std::vector<ActsExamples::ConstTrackContainer*> constTracks_v;
0317 constTracks_v.push_back(
0318 new ActsExamples::ConstTrackContainer(
0319 constTrackContainer,
0320 constTrackStateContainer));
0321 auto& constTracks = *(constTracks_v.front());
0322
0323
0324 #if Acts_VERSION_MAJOR >= 32
0325 const Acts::ConstProxyAccessor<unsigned int> constSeedNumber("seed");
0326 #else
0327 const Acts::ConstTrackAccessor<unsigned int> constSeedNumber("seed");
0328 #endif
0329
0330
0331 std::vector<ActsExamples::Trajectories*> acts_trajectories;
0332 acts_trajectories.reserve(init_trk_params.size());
0333
0334 ActsExamples::Trajectories::IndexedParameters parameters;
0335 std::vector<Acts::MultiTrajectoryTraits::IndexType> tips;
0336
0337 std::optional<unsigned int> lastSeed;
0338 for (const auto& track : constTracks) {
0339 if (!lastSeed) {
0340 lastSeed = constSeedNumber(track);
0341 }
0342
0343 if (constSeedNumber(track) != lastSeed.value()) {
0344
0345 acts_trajectories.push_back(new ActsExamples::Trajectories(
0346 constTracks.trackStateContainer(),
0347 tips, parameters));
0348
0349 tips.clear();
0350 parameters.clear();
0351 }
0352
0353 lastSeed = constSeedNumber(track);
0354
0355 tips.push_back(track.tipIndex());
0356 parameters.emplace(
0357 std::pair{track.tipIndex(),
0358 ActsExamples::TrackParameters{track.referenceSurface().getSharedPtr(),
0359 track.parameters(), track.covariance(),
0360 track.particleHypothesis()}});
0361 }
0362
0363 if (tips.empty()) {
0364 m_log->info("Last trajectory is empty");
0365 }
0366
0367
0368 acts_trajectories.push_back(new ActsExamples::Trajectories(
0369 constTracks.trackStateContainer(),
0370 std::move(tips), std::move(parameters)));
0371
0372 return std::make_tuple(std::move(acts_trajectories), std::move(constTracks_v));
0373 }
0374
0375 }