File indexing completed on 2025-12-16 09:23:34
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/TrackFinding/SeedingAlgorithmHashing.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/EventData/Seed.hpp"
0013 #include "ActsPlugins/Hashing/HashingAlgorithm.hpp"
0014 #include "ActsPlugins/Hashing/HashingTraining.hpp"
0015
0016 namespace ActsExamples {
0017
0018 namespace {
0019
0020
0021 template <typename external_spacepoint_t>
0022 struct SeedComparison {
0023 bool operator()(const Acts::Seed<external_spacepoint_t>& seed1,
0024 const Acts::Seed<external_spacepoint_t>& seed2) const {
0025 const auto& sp1 = seed1.sp();
0026 const auto& sp2 = seed2.sp();
0027
0028 for (std::size_t i = 0; i < sp1.size(); ++i) {
0029 if (sp1[i]->z() != sp2[i]->z()) {
0030 return sp1[i]->z() < sp2[i]->z();
0031 }
0032 }
0033
0034 for (std::size_t i = 0; i < sp1.size(); ++i) {
0035 if (sp1[i]->x() != sp2[i]->x()) {
0036 return sp1[i]->x() < sp2[i]->x();
0037 }
0038 }
0039
0040 for (std::size_t i = 0; i < sp1.size(); ++i) {
0041 if (sp1[i]->y() != sp2[i]->y()) {
0042 return sp1[i]->y() < sp2[i]->y();
0043 }
0044 }
0045
0046 return false;
0047 }
0048 };
0049
0050 }
0051
0052 SeedingAlgorithmHashing::SeedingAlgorithmHashing(
0053 SeedingAlgorithmHashing::Config cfg, Acts::Logging::Level lvl)
0054 : IAlgorithm("SeedingAlgorithmHashing", lvl), m_cfg(std::move(cfg)) {
0055 using SpacePointProxy_type = typename Acts::SpacePointContainer<
0056 SpacePointContainer<std::vector<const SimSpacePoint*>>,
0057 Acts::detail::RefHolder>::SpacePointProxyType;
0058
0059
0060
0061 m_cfg.seedFinderConfig.seedFilter =
0062 std::make_unique<Acts::SeedFilter<SpacePointProxy_type>>(
0063 m_cfg.seedFilterConfig);
0064
0065 m_cfg.seedFinderConfig = m_cfg.seedFinderConfig.calculateDerivedQuantities();
0066 m_cfg.seedFinderOptions = m_cfg.seedFinderOptions.calculateDerivedQuantities(
0067 m_cfg.seedFinderConfig);
0068 if (m_cfg.inputSpacePoints.empty()) {
0069 throw std::invalid_argument("Missing space point input collections");
0070 }
0071
0072 for (const auto& spName : m_cfg.inputSpacePoints) {
0073 if (spName.empty()) {
0074 throw std::invalid_argument("Invalid space point input collection");
0075 }
0076
0077 auto& handle = m_inputSpacePoints.emplace_back(
0078 std::make_unique<ReadDataHandle<SimSpacePointContainer>>(
0079 this,
0080 "InputSpacePoints#" + std::to_string(m_inputSpacePoints.size())));
0081 handle->initialize(spName);
0082 }
0083 if (m_cfg.outputSeeds.empty()) {
0084 throw std::invalid_argument("Missing seeds output collection");
0085 }
0086
0087 m_outputSeeds.initialize(m_cfg.outputSeeds);
0088 m_outputBuckets.initialize(m_cfg.outputBuckets);
0089
0090 if (m_cfg.gridConfig.rMax != m_cfg.seedFinderConfig.rMax &&
0091 m_cfg.allowSeparateRMax == false) {
0092 throw std::invalid_argument(
0093 "Inconsistent config rMax: using different values in gridConfig and "
0094 "seedFinderConfig. If values are intentional set allowSeparateRMax to "
0095 "true");
0096 }
0097
0098 if (m_cfg.seedFilterConfig.deltaRMin != m_cfg.seedFinderConfig.deltaRMin) {
0099 throw std::invalid_argument("Inconsistent config deltaRMin");
0100 }
0101
0102 if (m_cfg.gridConfig.deltaRMax != m_cfg.seedFinderConfig.deltaRMax) {
0103 throw std::invalid_argument("Inconsistent config deltaRMax");
0104 }
0105
0106 static_assert(
0107 std::numeric_limits<
0108 decltype(m_cfg.seedFinderConfig.deltaRMaxTopSP)>::has_quiet_NaN,
0109 "Value of deltaRMaxTopSP must support NaN values");
0110
0111 static_assert(
0112 std::numeric_limits<
0113 decltype(m_cfg.seedFinderConfig.deltaRMinTopSP)>::has_quiet_NaN,
0114 "Value of deltaRMinTopSP must support NaN values");
0115
0116 static_assert(
0117 std::numeric_limits<
0118 decltype(m_cfg.seedFinderConfig.deltaRMaxBottomSP)>::has_quiet_NaN,
0119 "Value of deltaRMaxBottomSP must support NaN values");
0120
0121 static_assert(
0122 std::numeric_limits<
0123 decltype(m_cfg.seedFinderConfig.deltaRMinBottomSP)>::has_quiet_NaN,
0124 "Value of deltaRMinBottomSP must support NaN values");
0125
0126 if (std::isnan(m_cfg.seedFinderConfig.deltaRMaxTopSP)) {
0127 m_cfg.seedFinderConfig.deltaRMaxTopSP = m_cfg.seedFinderConfig.deltaRMax;
0128 }
0129
0130 if (std::isnan(m_cfg.seedFinderConfig.deltaRMinTopSP)) {
0131 m_cfg.seedFinderConfig.deltaRMinTopSP = m_cfg.seedFinderConfig.deltaRMin;
0132 }
0133
0134 if (std::isnan(m_cfg.seedFinderConfig.deltaRMaxBottomSP)) {
0135 m_cfg.seedFinderConfig.deltaRMaxBottomSP = m_cfg.seedFinderConfig.deltaRMax;
0136 }
0137
0138 if (std::isnan(m_cfg.seedFinderConfig.deltaRMinBottomSP)) {
0139 m_cfg.seedFinderConfig.deltaRMinBottomSP = m_cfg.seedFinderConfig.deltaRMin;
0140 }
0141
0142 if (m_cfg.gridConfig.zMin != m_cfg.seedFinderConfig.zMin) {
0143 throw std::invalid_argument("Inconsistent config zMin");
0144 }
0145
0146 if (m_cfg.gridConfig.zMax != m_cfg.seedFinderConfig.zMax) {
0147 throw std::invalid_argument("Inconsistent config zMax");
0148 }
0149
0150 if (m_cfg.seedFilterConfig.maxSeedsPerSpM !=
0151 m_cfg.seedFinderConfig.maxSeedsPerSpM) {
0152 throw std::invalid_argument("Inconsistent config maxSeedsPerSpM");
0153 }
0154
0155 if (m_cfg.gridConfig.cotThetaMax != m_cfg.seedFinderConfig.cotThetaMax) {
0156 throw std::invalid_argument("Inconsistent config cotThetaMax");
0157 }
0158
0159 if (m_cfg.gridConfig.minPt != m_cfg.seedFinderConfig.minPt) {
0160 throw std::invalid_argument("Inconsistent config minPt");
0161 }
0162
0163 if (m_cfg.gridOptions.bFieldInZ != m_cfg.seedFinderOptions.bFieldInZ) {
0164 throw std::invalid_argument("Inconsistent config bFieldInZ");
0165 }
0166
0167 if (m_cfg.gridConfig.zBinEdges.size() - 1 != m_cfg.zBinNeighborsTop.size() &&
0168 m_cfg.zBinNeighborsTop.empty() == false) {
0169 throw std::invalid_argument("Inconsistent config zBinNeighborsTop");
0170 }
0171
0172 if (m_cfg.gridConfig.zBinEdges.size() - 1 !=
0173 m_cfg.zBinNeighborsBottom.size() &&
0174 m_cfg.zBinNeighborsBottom.empty() == false) {
0175 throw std::invalid_argument("Inconsistent config zBinNeighborsBottom");
0176 }
0177
0178 m_bottomBinFinder = std::make_unique<const Acts::GridBinFinder<3ul>>(
0179 m_cfg.numPhiNeighbors, m_cfg.zBinNeighborsBottom, 0);
0180 m_topBinFinder = std::make_unique<const Acts::GridBinFinder<3ul>>(
0181 m_cfg.numPhiNeighbors, m_cfg.zBinNeighborsTop, 0);
0182
0183 m_cfg.seedFinderConfig.seedFilter =
0184 std::make_unique<Acts::SeedFilter<SpacePointProxy_type>>(
0185 m_cfg.seedFilterConfig);
0186 m_seedFinder =
0187 Acts::SeedFinder<SpacePointProxy_type,
0188 Acts::CylindricalSpacePointGrid<SpacePointProxy_type>>(
0189 m_cfg.seedFinderConfig);
0190 m_hashing = ActsPlugins::HashingAlgorithm<const SimSpacePoint*,
0191 std::vector<const SimSpacePoint*>>(
0192 m_cfg.hashingConfig);
0193 m_hashingTraining =
0194 ActsPlugins::HashingTrainingAlgorithm<std::vector<const SimSpacePoint*>>(
0195 m_cfg.hashingTrainingConfig);
0196 }
0197
0198 ProcessCode SeedingAlgorithmHashing::execute(
0199 const AlgorithmContext& ctx) const {
0200 ACTS_DEBUG("Start of SeedingAlgorithmHashing execute");
0201 using SpacePointPtrVector = std::vector<const SimSpacePoint*>;
0202
0203
0204
0205
0206 std::size_t nSpacePoints = 0;
0207 for (const auto& isp : m_inputSpacePoints) {
0208 nSpacePoints += (*isp)(ctx).size();
0209 }
0210
0211 SpacePointPtrVector spacePointPtrs;
0212 spacePointPtrs.reserve(nSpacePoints);
0213 for (const auto& isp : m_inputSpacePoints) {
0214 for (const SimSpacePoint& spacePoint : (*isp)(ctx)) {
0215
0216
0217
0218 spacePointPtrs.push_back(&spacePoint);
0219 }
0220 }
0221
0222
0223 Acts::SpacePointContainerConfig spConfig;
0224 spConfig.useDetailedDoubleMeasurementInfo =
0225 m_cfg.seedFinderConfig.useDetailedDoubleMeasurementInfo;
0226
0227 Acts::SpacePointContainerOptions spOptions;
0228 spOptions.beamPos = {0., 0.};
0229
0230
0231 ActsPlugins::AnnoyModel annoyModel =
0232 m_hashingTraining.execute(spacePointPtrs);
0233
0234 static thread_local std::vector<SpacePointPtrVector> bucketsPtrs;
0235 bucketsPtrs.clear();
0236 m_hashing.execute(spacePointPtrs, &annoyModel, bucketsPtrs);
0237
0238
0239
0240 std::size_t maxNSpacePoints = 0;
0241 std::size_t inSpacePoints = 0;
0242 for (const SpacePointPtrVector& bucket : bucketsPtrs) {
0243 inSpacePoints = bucket.size();
0244 if (inSpacePoints > maxNSpacePoints) {
0245 maxNSpacePoints = inSpacePoints;
0246 }
0247 }
0248
0249 using value_type = typename Acts::SpacePointContainer<
0250 SpacePointContainer<std::vector<const SimSpacePoint*>>,
0251 Acts::detail::RefHolder>::SpacePointProxyType;
0252 using seed_type = Acts::Seed<value_type>;
0253
0254
0255 static thread_local std::set<SimSeed, SeedComparison<SimSpacePoint>> seedsSet;
0256 seedsSet.clear();
0257 static thread_local decltype(m_seedFinder)::SeedingState state;
0258 state.spacePointMutableData.resize(maxNSpacePoints);
0259
0260 for (SpacePointPtrVector& bucket : bucketsPtrs) {
0261 std::set<seed_type, SeedComparison<value_type>> seedsSetForBucket;
0262 state.spacePointMutableData.clear();
0263 state.spacePointMutableData.resize(maxNSpacePoints);
0264
0265
0266 SpacePointContainer container(bucket);
0267
0268 Acts::SpacePointContainer<decltype(container), Acts::detail::RefHolder>
0269 spContainer(spConfig, spOptions, container);
0270
0271
0272 Acts::CylindricalSpacePointGrid<value_type> grid =
0273 Acts::CylindricalSpacePointGridCreator::createGrid<value_type>(
0274 m_cfg.gridConfig, m_cfg.gridOptions);
0275 Acts::CylindricalSpacePointGridCreator::fillGrid(
0276 m_cfg.seedFinderConfig, m_cfg.seedFinderOptions, grid,
0277 spContainer.begin(), spContainer.end());
0278
0279
0280
0281
0282 float minRange = std::numeric_limits<float>::max();
0283 float maxRange = std::numeric_limits<float>::lowest();
0284 for (const auto& coll : grid) {
0285 if (coll.empty()) {
0286 continue;
0287 }
0288 const auto* firstEl = coll.front();
0289 const auto* lastEl = coll.back();
0290 minRange = std::min(firstEl->radius(), minRange);
0291 maxRange = std::max(lastEl->radius(), maxRange);
0292 }
0293
0294 std::array<std::vector<std::size_t>, 3ul> navigation;
0295 navigation[1ul] = m_cfg.seedFinderConfig.zBinsCustomLooping;
0296
0297
0298 auto spacePointsGrouping = Acts::CylindricalBinnedGroup<value_type>(
0299 std::move(grid), *m_bottomBinFinder, *m_topBinFinder,
0300 std::move(navigation));
0301
0302
0303 const Acts::Range1D<float> rMiddleSPRange(
0304 minRange + m_cfg.seedFinderConfig.deltaRMiddleMinSPRange,
0305 maxRange - m_cfg.seedFinderConfig.deltaRMiddleMaxSPRange);
0306
0307
0308
0309 for (const auto [bottom, middle, top] : spacePointsGrouping) {
0310 m_seedFinder.createSeedsForGroup(
0311 m_cfg.seedFinderOptions, state, spacePointsGrouping.grid(),
0312 seedsSetForBucket, bottom, middle, top, rMiddleSPRange);
0313 }
0314
0315
0316
0317 for (const seed_type& seed : seedsSetForBucket) {
0318 const std::array<const value_type*, 3>& sps = seed.sp();
0319 const SimSpacePoint* bottom = sps[0]->externalSpacePoint();
0320 const SimSpacePoint* middle = sps[1]->externalSpacePoint();
0321 const SimSpacePoint* top = sps[2]->externalSpacePoint();
0322
0323 SimSeed toAdd(*bottom, *middle, *top);
0324 toAdd.setVertexZ(seed.z());
0325 toAdd.setQuality(seed.seedQuality());
0326
0327 seedsSet.insert(toAdd);
0328 }
0329 }
0330
0331
0332 SimSeedContainer seeds;
0333 seeds.reserve(seedsSet.size());
0334 for (const SimSeed& seed : seedsSet) {
0335 seeds.push_back(seed);
0336 }
0337
0338 ACTS_INFO("Created " << seeds.size() << " track seeds from "
0339 << spacePointPtrs.size() << " space points");
0340
0341 m_outputSeeds(ctx, SimSeedContainer{seeds});
0342 std::vector<SimSpacePointContainer> buckets;
0343 for (const SpacePointPtrVector& bucket : bucketsPtrs) {
0344 SimSpacePointContainer bucketSP;
0345 for (const SimSpacePoint* spacePoint : bucket) {
0346 bucketSP.push_back(*spacePoint);
0347 }
0348 buckets.push_back(bucketSP);
0349 }
0350 m_outputBuckets(ctx, std::vector<SimSpacePointContainer>{buckets});
0351
0352 ACTS_DEBUG("End of SeedingAlgorithmHashing execute");
0353 return ProcessCode::SUCCESS;
0354 }
0355
0356 }