File indexing completed on 2025-08-05 08:09:49
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/TrackFindingExaTrkX/TrackFindingFromPrototrackAlgorithm.hpp"
0010
0011 #include "Acts/EventData/ProxyAccessor.hpp"
0012 #include "ActsExamples/EventData/IndexSourceLink.hpp"
0013 #include "ActsExamples/EventData/MeasurementCalibration.hpp"
0014
0015 #include <boost/accumulators/accumulators.hpp>
0016 #include <boost/accumulators/statistics.hpp>
0017
0018 namespace {
0019
0020 using namespace ActsExamples;
0021
0022 struct ProtoTrackSourceLinkAccessor
0023 : GeometryIdMultisetAccessor<IndexSourceLink> {
0024 using BaseIterator = GeometryIdMultisetAccessor<IndexSourceLink>::Iterator;
0025 using Iterator = Acts::SourceLinkAdapterIterator<BaseIterator>;
0026
0027 std::unique_ptr<const Acts::Logger> loggerPtr;
0028 Container protoTrackSourceLinks;
0029
0030
0031 std::pair<Iterator, Iterator> range(const Acts::Surface& surface) const {
0032 const auto& logger = *loggerPtr;
0033
0034 if (protoTrackSourceLinks.contains(surface.geometryId())) {
0035 auto [begin, end] =
0036 protoTrackSourceLinks.equal_range(surface.geometryId());
0037 ACTS_VERBOSE("Select " << std::distance(begin, end)
0038 << " source-links from prototrack on "
0039 << surface.geometryId());
0040 return {Iterator{begin}, Iterator{end}};
0041 }
0042
0043 assert(container != nullptr);
0044 auto [begin, end] = container->equal_range(surface.geometryId());
0045 ACTS_VERBOSE("Select " << std::distance(begin, end)
0046 << " source-links from collection on "
0047 << surface.geometryId());
0048 return {Iterator{begin}, Iterator{end}};
0049 }
0050 };
0051 }
0052
0053 namespace ActsExamples {
0054
0055 TrackFindingFromPrototrackAlgorithm::TrackFindingFromPrototrackAlgorithm(
0056 Config cfg, Acts::Logging::Level lvl)
0057 : IAlgorithm(cfg.tag + "CkfFromProtoTracks", lvl), m_cfg(cfg) {
0058 m_inputInitialTrackParameters.initialize(m_cfg.inputInitialTrackParameters);
0059 m_inputMeasurements.initialize(m_cfg.inputMeasurements);
0060 m_inputProtoTracks.initialize(m_cfg.inputProtoTracks);
0061 m_inputSourceLinks.initialize(m_cfg.inputSourceLinks);
0062 m_outputTracks.initialize(m_cfg.outputTracks);
0063 }
0064
0065 ActsExamples::ProcessCode TrackFindingFromPrototrackAlgorithm::execute(
0066 const ActsExamples::AlgorithmContext& ctx) const {
0067 const auto& measurements = m_inputMeasurements(ctx);
0068 const auto& sourceLinks = m_inputSourceLinks(ctx);
0069 const auto& protoTracks = m_inputProtoTracks(ctx);
0070 const auto& initialParameters = m_inputInitialTrackParameters(ctx);
0071
0072 if (initialParameters.size() != protoTracks.size()) {
0073 ACTS_FATAL("Inconsistent number of parameters and prototracks");
0074 return ProcessCode::ABORT;
0075 }
0076
0077
0078 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
0079 Acts::Vector3{0., 0., 0.});
0080
0081 Acts::PropagatorPlainOptions pOptions;
0082 pOptions.maxSteps = 10000;
0083
0084 PassThroughCalibrator pcalibrator;
0085 MeasurementCalibratorAdapter calibrator(pcalibrator, measurements);
0086 Acts::GainMatrixUpdater kfUpdater;
0087 Acts::GainMatrixSmoother kfSmoother;
0088 Acts::MeasurementSelector measSel{m_cfg.measurementSelectorCfg};
0089
0090 Acts::CombinatorialKalmanFilterExtensions<Acts::VectorMultiTrajectory>
0091 extensions;
0092 extensions.calibrator.connect<&MeasurementCalibratorAdapter::calibrate>(
0093 &calibrator);
0094 extensions.updater.connect<
0095 &Acts::GainMatrixUpdater::operator()<Acts::VectorMultiTrajectory>>(
0096 &kfUpdater);
0097 extensions.measurementSelector
0098 .connect<&Acts::MeasurementSelector::select<Acts::VectorMultiTrajectory>>(
0099 &measSel);
0100
0101
0102 ProtoTrackSourceLinkAccessor sourceLinkAccessor;
0103 sourceLinkAccessor.loggerPtr = logger().clone("SourceLinkAccessor");
0104 sourceLinkAccessor.container = &sourceLinks;
0105
0106 Acts::SourceLinkAccessorDelegate<IndexSourceLinkAccessor::Iterator>
0107 slAccessorDelegate;
0108 slAccessorDelegate.connect<&ProtoTrackSourceLinkAccessor::range>(
0109 &sourceLinkAccessor);
0110
0111
0112 TrackFindingAlgorithm::TrackFinderOptions options(
0113 ctx.geoContext, ctx.magFieldContext, ctx.calibContext, slAccessorDelegate,
0114 extensions, pOptions, &(*pSurface));
0115
0116
0117 ACTS_DEBUG("Invoke track finding with " << initialParameters.size()
0118 << " seeds.");
0119
0120 auto trackContainer = std::make_shared<Acts::VectorTrackContainer>();
0121 auto trackStateContainer = std::make_shared<Acts::VectorMultiTrajectory>();
0122
0123 TrackContainer tracks(trackContainer, trackStateContainer);
0124
0125 tracks.addColumn<unsigned int>("trackGroup");
0126 Acts::ProxyAccessor<unsigned int> seedNumber("trackGroup");
0127
0128 std::size_t nSeed = 0;
0129 std::size_t nFailed = 0;
0130
0131 std::vector<std::size_t> nTracksPerSeeds;
0132 nTracksPerSeeds.reserve(initialParameters.size());
0133
0134 for (auto i = 0ul; i < initialParameters.size(); ++i) {
0135 sourceLinkAccessor.protoTrackSourceLinks.clear();
0136
0137
0138 for (const auto hitIndex : protoTracks.at(i)) {
0139 if (auto it = sourceLinks.nth(hitIndex); it != sourceLinks.end()) {
0140 sourceLinkAccessor.protoTrackSourceLinks.insert(*it);
0141 } else {
0142 ACTS_FATAL("Proto track " << i << " contains invalid hit index"
0143 << hitIndex);
0144 return ProcessCode::ABORT;
0145 }
0146 }
0147
0148 auto result = (*m_cfg.findTracks)(initialParameters.at(i), options, tracks);
0149 nSeed++;
0150
0151 if (!result.ok()) {
0152 nFailed++;
0153 ACTS_WARNING("Track finding failed for proto track " << i << " with error"
0154 << result.error());
0155 continue;
0156 }
0157
0158 auto& tracksForSeed = result.value();
0159
0160 nTracksPerSeeds.push_back(tracksForSeed.size());
0161
0162 for (auto& track : tracksForSeed) {
0163
0164
0165 seedNumber(track) = nSeed - 1;
0166 }
0167 }
0168
0169 {
0170 std::lock_guard<std::mutex> guard(m_mutex);
0171
0172 std::copy(nTracksPerSeeds.begin(), nTracksPerSeeds.end(),
0173 std::back_inserter(m_nTracksPerSeeds));
0174 }
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184 ACTS_INFO("Event " << ctx.eventNumber << ": " << nFailed << " / " << nSeed
0185 << " failed (" << ((100.f * nFailed) / nSeed) << "%)");
0186 ACTS_DEBUG("Finalized track finding with " << tracks.size()
0187 << " track candidates.");
0188 auto constTrackStateContainer =
0189 std::make_shared<Acts::ConstVectorMultiTrajectory>(
0190 std::move(*trackStateContainer));
0191
0192 auto constTrackContainer = std::make_shared<Acts::ConstVectorTrackContainer>(
0193 std::move(*trackContainer));
0194
0195 ConstTrackContainer constTracks{constTrackContainer,
0196 constTrackStateContainer};
0197
0198 m_outputTracks(ctx, std::move(constTracks));
0199 return ActsExamples::ProcessCode::SUCCESS;
0200 }
0201
0202 ActsExamples::ProcessCode TrackFindingFromPrototrackAlgorithm::finalize() {
0203 assert(std::distance(m_nTracksPerSeeds.begin(), m_nTracksPerSeeds.end()) > 0);
0204
0205 ACTS_INFO("TrackFindingFromPrototracksAlgorithm statistics:");
0206 namespace ba = boost::accumulators;
0207 using Accumulator = ba::accumulator_set<
0208 float, ba::features<ba::tag::sum, ba::tag::mean, ba::tag::variance>>;
0209
0210 Accumulator totalAcc;
0211 std::for_each(m_nTracksPerSeeds.begin(), m_nTracksPerSeeds.end(),
0212 [&](auto v) { totalAcc(static_cast<float>(v)); });
0213 ACTS_INFO("- total number tracks: " << ba::sum(totalAcc));
0214 ACTS_INFO("- avg tracks per seed: " << ba::mean(totalAcc) << " +- "
0215 << std::sqrt(ba::variance(totalAcc)));
0216
0217 return {};
0218 }
0219
0220 }