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