Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-08-28 08:12:01

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include "Acts/Seeding2/TripletSeeder.hpp"
0010 
0011 #include "Acts/EventData/SpacePointContainer2.hpp"
0012 #include "Acts/Seeding2/DoubletSeedFinder.hpp"
0013 #include "Acts/Seeding2/TripletSeedFinder.hpp"
0014 
0015 #include <Eigen/Dense>
0016 
0017 namespace Acts::Experimental {
0018 
0019 namespace {
0020 
0021 template <typename DoubletCollections>
0022 void createAndFilterTriplets(TripletSeeder::Cache& cache,
0023                              const TripletSeedFinder& tripletFinder,
0024                              const ITripletSeedFilter& filter,
0025                              const SpacePointContainer2& spacePoints,
0026                              DoubletCollections bottomDoublets,
0027                              const ConstSpacePointProxy2& spM,
0028                              DoubletCollections topDoublets) {
0029   for (auto bottomDoublet : bottomDoublets) {
0030     if (topDoublets.empty()) {
0031       break;
0032     }
0033 
0034     cache.tripletTopCandidates.clear();
0035     tripletFinder.createTripletTopCandidates(spacePoints, spM, bottomDoublet,
0036                                              topDoublets,
0037                                              cache.tripletTopCandidates);
0038 
0039     filter.filterTripletTopCandidates(spacePoints, spM, bottomDoublet,
0040                                       cache.tripletTopCandidates);
0041   }
0042 }
0043 
0044 template <typename SpacePointCollections>
0045 void createSeedsFromGroupsImpl(
0046     const Logger& logger, TripletSeeder::Cache& cache,
0047     const DoubletSeedFinder& bottomFinder, const DoubletSeedFinder& topFinder,
0048     const TripletSeedFinder& tripletFinder, const ITripletSeedFilter& filter,
0049     const SpacePointContainer2& spacePoints,
0050     SpacePointCollections& bottomSpGroups,
0051     const ConstSpacePointProxy2& middleSp, SpacePointCollections& topSpGroups,
0052     SeedContainer2& outputSeeds) {
0053   MiddleSpInfo middleSpInfo = DoubletSeedFinder::computeMiddleSpInfo(middleSp);
0054 
0055   // create middle-top doublets
0056   cache.topDoublets.clear();
0057   for (auto& topSpGroup : topSpGroups) {
0058     topFinder.createDoublets(middleSp, middleSpInfo, topSpGroup,
0059                              cache.topDoublets);
0060   }
0061 
0062   // no top SP found -> cannot form any triplet
0063   if (cache.topDoublets.empty()) {
0064     ACTS_VERBOSE("No compatible Tops, returning");
0065     return;
0066   }
0067 
0068   if (!filter.sufficientTopDoublets(spacePoints, middleSp, cache.topDoublets)) {
0069     return;
0070   }
0071 
0072   // create middle-bottom doublets
0073   cache.bottomDoublets.clear();
0074   for (auto& bottomSpGroup : bottomSpGroups) {
0075     bottomFinder.createDoublets(middleSp, middleSpInfo, bottomSpGroup,
0076                                 cache.bottomDoublets);
0077   }
0078 
0079   // no bottom SP found -> cannot form any triplet
0080   if (cache.bottomDoublets.empty()) {
0081     ACTS_VERBOSE("No compatible Bottoms, returning");
0082     return;
0083   }
0084 
0085   ACTS_VERBOSE("Candidates: " << cache.bottomDoublets.size() << " bottoms and "
0086                               << cache.topDoublets.size()
0087                               << " tops for middle candidate indexed "
0088                               << middleSp.index());
0089 
0090   // combine doublets to triplets
0091   if (tripletFinder.config().sortedByCotTheta) {
0092     cache.bottomDoublets.sortByCotTheta({0, cache.bottomDoublets.size()},
0093                                         cache.sortedBottoms);
0094     cache.topDoublets.sortByCotTheta({0, cache.topDoublets.size()},
0095                                      cache.sortedTops);
0096 
0097     createAndFilterTriplets(cache, tripletFinder, filter, spacePoints,
0098                             cache.bottomDoublets.subset(cache.sortedBottoms),
0099                             middleSp,
0100                             cache.topDoublets.subset(cache.sortedTops));
0101   } else {
0102     createAndFilterTriplets(cache, tripletFinder, filter, spacePoints,
0103                             cache.bottomDoublets.range(), middleSp,
0104                             cache.topDoublets.range());
0105   }
0106 
0107   filter.filterTripletsMiddleFixed(spacePoints, outputSeeds);
0108 }
0109 
0110 }  // namespace
0111 
0112 TripletSeeder::TripletSeeder(std::unique_ptr<const Logger> logger_)
0113     : m_logger(std::move(logger_)) {
0114   if (m_logger == nullptr) {
0115     throw std::invalid_argument("TripletSeeder: logger cannot be null");
0116   }
0117 }
0118 
0119 void TripletSeeder::createSeedsFromGroup(
0120     Cache& cache, const DoubletSeedFinder& bottomFinder,
0121     const DoubletSeedFinder& topFinder, const TripletSeedFinder& tripletFinder,
0122     const ITripletSeedFilter& filter, const SpacePointContainer2& spacePoints,
0123     SpacePointContainer2::ConstSubset& bottomSps,
0124     const ConstSpacePointProxy2& middleSp,
0125     SpacePointContainer2::ConstSubset& topSps,
0126     SeedContainer2& outputSeeds) const {
0127   assert((bottomFinder.config().spacePointsSortedByRadius ==
0128           topFinder.config().spacePointsSortedByRadius) &&
0129          "Inconsistent space point sorting");
0130 
0131   std::array<SpacePointContainer2::ConstSubset, 1> bottomSpGroups{bottomSps};
0132   std::array<SpacePointContainer2::ConstSubset, 1> topSpGroups{topSps};
0133 
0134   createSeedsFromGroupsImpl(*m_logger, cache, bottomFinder, topFinder,
0135                             tripletFinder, filter, spacePoints, bottomSpGroups,
0136                             middleSp, topSpGroups, outputSeeds);
0137 }
0138 
0139 void TripletSeeder::createSeedsFromGroups(
0140     Cache& cache, const DoubletSeedFinder& bottomFinder,
0141     const DoubletSeedFinder& topFinder, const TripletSeedFinder& tripletFinder,
0142     const ITripletSeedFilter& filter, const SpacePointContainer2& spacePoints,
0143     const std::span<SpacePointContainer2::ConstRange>& bottomSpGroups,
0144     const SpacePointContainer2::ConstRange& middleSpGroup,
0145     const std::span<SpacePointContainer2::ConstRange>& topSpGroups,
0146     const std::pair<float, float>& radiusRangeForMiddle,
0147     SeedContainer2& outputSeeds) const {
0148   assert((bottomFinder.config().spacePointsSortedByRadius ==
0149           topFinder.config().spacePointsSortedByRadius) &&
0150          "Inconsistent space point sorting");
0151   const bool spacePointsSortedByRadius =
0152       bottomFinder.config().spacePointsSortedByRadius;
0153 
0154   if (middleSpGroup.empty()) {
0155     return;
0156   }
0157 
0158   if (spacePointsSortedByRadius) {
0159     // Initialize initial offsets for bottom and top space points with binary
0160     // search. This requires at least one middle space point to be present which
0161     // is already checked above.
0162     const ConstSpacePointProxy2 firstMiddleSp = middleSpGroup.front();
0163     const float firstMiddleSpR = firstMiddleSp.zr()[1];
0164 
0165     for (auto& bottomSpGroup : bottomSpGroups) {
0166       // Find the first bottom space point that is within the deltaRMax of the
0167       // first middle space point.
0168       const auto low = std::ranges::lower_bound(
0169           bottomSpGroup, firstMiddleSpR - bottomFinder.config().deltaRMax, {},
0170           [&](const ConstSpacePointProxy2& sp) { return sp.zr()[1]; });
0171       bottomSpGroup = bottomSpGroup.subrange(low - bottomSpGroup.begin());
0172     }
0173 
0174     for (auto& topSpGroup : topSpGroups) {
0175       // Find the first top space point that is within the deltaRMin of the
0176       // first middle space point.
0177       const auto low = std::ranges::lower_bound(
0178           topSpGroup, firstMiddleSpR + topFinder.config().deltaRMin, {},
0179           [&](const ConstSpacePointProxy2& sp) { return sp.zr()[1]; });
0180       topSpGroup = topSpGroup.subrange(low - topSpGroup.begin());
0181     }
0182   }
0183 
0184   for (ConstSpacePointProxy2 spM : middleSpGroup) {
0185     const float rM = spM.zr()[1];
0186 
0187     if (spacePointsSortedByRadius) {
0188       // check if spM is outside our radial region of interest
0189       if (rM < radiusRangeForMiddle.first) {
0190         continue;
0191       }
0192       if (rM > radiusRangeForMiddle.second) {
0193         // break because SPs are sorted in r
0194         break;
0195       }
0196     }
0197 
0198     createSeedsFromGroupsImpl(*m_logger, cache, bottomFinder, topFinder,
0199                               tripletFinder, filter, spacePoints,
0200                               bottomSpGroups, spM, topSpGroups, outputSeeds);
0201   }
0202 }
0203 
0204 }  // namespace Acts::Experimental