Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-02 09:31:02

0001 // SPDX-License-Identifier: LGPL-3.0-or-later
0002 // Copyright (C) 2023 - 2026, Joe Osborn, Dmitry Romanov, Wouter Deconinck
0003 
0004 #pragma once
0005 
0006 #include <Acts/Utilities/Logger.hpp>
0007 #include <algorithms/algorithm.h>
0008 #include <boost/container/detail/std_fwd.hpp>
0009 #include <edm4eic/TrackParametersCollection.h>
0010 #include <edm4eic/TrackSeedCollection.h>
0011 #include <edm4eic/TrackerHitCollection.h>
0012 #include <array>
0013 #include <cstddef>
0014 #include <memory>
0015 #include <optional>
0016 #include <string>
0017 #include <string_view>
0018 #include <tuple>
0019 #include <utility>
0020 #include <variant>
0021 #include <vector>
0022 
0023 #include "ActsGeometryProvider.h"
0024 #include "TrackSeedingConfig.h"
0025 #include "algorithms/interfaces/ActsSvc.h"
0026 #include "algorithms/interfaces/WithPodConfig.h"
0027 
0028 // Define version availability macros for each seeding method
0029 // Seeding requires Acts >= 47, when Seeding2 was renamed to Seeding.
0030 // Seeding2 requires Acts >= 45.3: earlier 45.x releases had ambiguous
0031 // SeedContainer2::assignSpacePointContainer overloads for lvalues; this was
0032 // resolved in v45.3.0 by changing the by-value overload to rvalue-ref.
0033 #define TRACKSEEDING_HAS_SEEDING (Acts_VERSION_MAJOR >= 47)
0034 #define TRACKSEEDING_HAS_SEEDING2                                                                  \
0035   (Acts_VERSION_MAJOR > 45 || (Acts_VERSION_MAJOR == 45 && Acts_VERSION_MINOR >= 3)) &&            \
0036       (Acts_VERSION_MAJOR < 47)
0037 #define TRACKSEEDING_HAS_ORTHOGONAL (Acts_VERSION_MAJOR <= 46)
0038 
0039 // Acts version-specific includes
0040 #if TRACKSEEDING_HAS_SEEDING
0041 #include <Acts/Seeding/BroadTripletSeedFilter.hpp>
0042 #include <Acts/Seeding/DoubletSeedFinder.hpp>
0043 #include <Acts/Seeding/TripletSeedFinder.hpp>
0044 #include <Acts/Seeding/TripletSeeder.hpp>
0045 #endif
0046 
0047 #if TRACKSEEDING_HAS_SEEDING2
0048 #include <Acts/Seeding2/BroadTripletSeedFilter.hpp>
0049 #include <Acts/Seeding2/DoubletSeedFinder.hpp>
0050 #include <Acts/Seeding2/TripletSeedFinder.hpp>
0051 #include <Acts/Seeding2/TripletSeeder.hpp>
0052 #endif
0053 
0054 #if TRACKSEEDING_HAS_ORTHOGONAL
0055 #include <Acts/EventData/Seed.hpp>
0056 #include <Acts/EventData/SpacePointContainer.hpp>
0057 #include <Acts/Seeding/SeedFilterConfig.hpp>
0058 #include <Acts/Seeding/SeedFinderConfig.hpp>
0059 #include <Acts/Seeding/SeedFinderOrthogonalConfig.hpp>
0060 #include <Acts/Utilities/HashedString.hpp>
0061 #include <Acts/Utilities/Holders.hpp>
0062 #if __has_include(<ActsExamples/EventData/SpacePointContainer.hpp>)
0063 #include <ActsExamples/EventData/SpacePointContainer.hpp>
0064 #else
0065 #include <any>
0066 #include <stdexcept>
0067 #endif
0068 #include "SpacePoint.h"
0069 #endif
0070 
0071 namespace eicrecon {
0072 
0073 #if TRACKSEEDING_HAS_ORTHOGONAL
0074 // SpacePointContainerAdapter only needed for Orthogonal API
0075 #if !__has_include(<ActsExamples/EventData/SpacePointContainer.hpp>)
0076 /// Adapter to wrap a collection of space points for use with Acts::SpacePointContainer.
0077 /// This replaces ActsExamples::SpacePointContainer<T>, which was removed in Acts >= 46
0078 /// (see https://github.com/acts-project/acts/pull/5088).
0079 template <typename collection_t> class SpacePointContainerAdapter {
0080 public:
0081   using CollectionType = collection_t;
0082   using ValueType      = typename CollectionType::value_type;
0083 
0084   friend class Acts::SpacePointContainer<SpacePointContainerAdapter<collection_t>,
0085                                          Acts::detail::RefHolder>;
0086 
0087   SpacePointContainerAdapter() = delete;
0088   explicit SpacePointContainerAdapter(CollectionType& container) : m_storage(container) {}
0089 
0090 private:
0091   std::size_t size_impl() const { return storage().size(); }
0092   float x_impl(std::size_t idx) const { return storage()[idx]->x(); }
0093   float y_impl(std::size_t idx) const { return storage()[idx]->y(); }
0094   float z_impl(std::size_t idx) const { return storage()[idx]->z(); }
0095   float varianceR_impl(std::size_t idx) const { return storage()[idx]->varianceR(); }
0096   float varianceZ_impl(std::size_t idx) const { return storage()[idx]->varianceZ(); }
0097   const ValueType& get_impl(std::size_t idx) const { return storage()[idx]; }
0098   std::any component_impl(Acts::HashedString /*key*/, std::size_t /*n*/) const {
0099     throw std::runtime_error(
0100         "SpacePointContainerAdapter does not support detailed double measurement "
0101         "information (useDetailedDoubleMeasurementInfo). Use Acts::SpacePointContainer2 "
0102         "if this feature is required.");
0103   }
0104 
0105   const CollectionType& storage() const { return *m_storage; }
0106 
0107   Acts::detail::RefHolder<CollectionType> m_storage;
0108 };
0109 #endif
0110 #endif // TRACKSEEDING_HAS_ORTHOGONAL
0111 
0112 namespace trackseeding_detail {
0113 
0114 #if TRACKSEEDING_HAS_SEEDING2 || TRACKSEEDING_HAS_SEEDING
0115   struct SeedingData {
0116     std::shared_ptr<const Acts::Logger> actsLogger{nullptr};
0117     Acts::BroadTripletSeedFilter::Config filterConfig;
0118     std::optional<Acts::TripletSeeder> seedFinder;
0119     std::unique_ptr<Acts::DoubletSeedFinder> bottomDoubletFinder{nullptr};
0120     std::unique_ptr<Acts::DoubletSeedFinder> topDoubletFinder{nullptr};
0121     std::unique_ptr<Acts::TripletSeedFinder> tripletFinder{nullptr};
0122   };
0123 #endif
0124 
0125 #if TRACKSEEDING_HAS_ORTHOGONAL
0126   template <typename proxy_t> struct OrthogonalDataT {
0127     std::shared_ptr<const Acts::Logger> actsLogger{nullptr};
0128     Acts::SeedFilterConfig seedFilterConfig;
0129     Acts::SeedFinderOptions seedFinderOptions;
0130     Acts::SeedFinderOrthogonalConfig<proxy_t> seedFinderConfig;
0131   };
0132 #endif
0133 
0134 } // namespace trackseeding_detail
0135 
0136 using TrackSeedingAlgorithm = algorithms::Algorithm<
0137     algorithms::Input<edm4eic::TrackerHitCollection>,
0138     algorithms::Output<edm4eic::TrackSeedCollection, edm4eic::TrackParametersCollection>>;
0139 
0140 /// Track seeding algorithm with automatic implementation selection based on Acts version.
0141 /// - seedingMethod=Auto: uses Seeding2 when available, otherwise Orthogonal
0142 /// - seedingMethod can also force a specific implementation when it is compiled in
0143 class TrackSeeding : public TrackSeedingAlgorithm, public WithPodConfig<TrackSeedingConfig> {
0144 public:
0145 #if TRACKSEEDING_HAS_ORTHOGONAL
0146   // Orthogonal API types
0147 #if __has_include(<ActsExamples/EventData/SpacePointContainer.hpp>)
0148   using SpacePointContainerType = ActsExamples::SpacePointContainer<std::vector<const SpacePoint*>>;
0149 #else
0150   using SpacePointContainerType = SpacePointContainerAdapter<std::vector<const SpacePoint*>>;
0151 #endif
0152   using proxy_type =
0153       typename Acts::SpacePointContainer<SpacePointContainerType,
0154                                          Acts::detail::RefHolder>::SpacePointProxyType;
0155 #endif
0156 
0157   TrackSeeding(std::string_view name)
0158       : TrackSeedingAlgorithm{name,
0159                               {"inputTrackerHits"},
0160                               {"outputTrackSeeds", "outputTrackParameters"},
0161                               "create track seeds from tracker hits"}
0162 #if TRACKSEEDING_HAS_SEEDING2 && TRACKSEEDING_HAS_ORTHOGONAL
0163       , m_seedingData(std::in_place_type<SeedingData>) // Default to Seeding2 when both available
0164 #endif
0165   {
0166   }
0167 
0168   void init() final;
0169   void process(const Input&, const Output&) const final;
0170 
0171 private:
0172   const algorithms::ActsSvc& m_actsSvc{algorithms::ActsSvc::instance()};
0173   const std::shared_ptr<const ActsGeometryProvider> m_geoSvc{m_actsSvc.acts_geometry_provider()};
0174 
0175 #if TRACKSEEDING_HAS_SEEDING2 || TRACKSEEDING_HAS_SEEDING
0176   using SeedingData = trackseeding_detail::SeedingData;
0177 #endif
0178 
0179 #if TRACKSEEDING_HAS_ORTHOGONAL
0180   using OrthogonalData = trackseeding_detail::OrthogonalDataT<proxy_type>;
0181 #endif
0182 
0183 #if TRACKSEEDING_HAS_SEEDING2 && TRACKSEEDING_HAS_ORTHOGONAL
0184   // Both methods available: Use runtime dispatch with variant
0185   std::variant<SeedingData, OrthogonalData> m_seedingData;
0186 
0187   // Helper to access Seeding2 logger
0188   const Acts::Logger& actsLogger() const {
0189     return *std::get<SeedingData>(m_seedingData).actsLogger;
0190   }
0191 #elif TRACKSEEDING_HAS_SEEDING2 || TRACKSEEDING_HAS_SEEDING
0192   // Only Seeding2 available
0193   SeedingData m_seedingData;
0194 
0195   const Acts::Logger& actsLogger() const { return *m_seedingData.actsLogger; }
0196 #elif TRACKSEEDING_HAS_ORTHOGONAL
0197   // Only Orthogonal available
0198   OrthogonalData m_seedingData;
0199 
0200   const Acts::Logger& actsLogger() const { return *m_seedingData.actsLogger; }
0201 #else
0202 #error "No seeding method available - check Acts version compatibility"
0203 #endif
0204 
0205   // Resolved seeding method (after resolving Auto in init())
0206   TrackSeedingConfig::SeedingMethod m_resolvedMethod{TrackSeedingConfig::SeedingMethod::Auto};
0207 
0208   // Shared helper functions (used by both implementations)
0209   static int determineCharge(std::vector<std::pair<float, float>>& positions,
0210                              const std::pair<float, float>& PCA,
0211                              std::tuple<float, float, float>& RX0Y0);
0212   static std::pair<float, float> findPCA(std::tuple<float, float, float>& circleParams);
0213   static std::tuple<float, float, float> circleFit(std::vector<std::pair<float, float>>& positions);
0214   static std::tuple<float, float> lineFit(std::vector<std::pair<float, float>>& positions);
0215 
0216   // Shared core physics calculation for track parameter estimation
0217   static std::optional<edm4eic::MutableTrackParameters> computeTrackParametersFromFit(
0218       const std::vector<std::pair<float, float>>& xyPositions,
0219       const std::vector<std::pair<float, float>>& rzPositions, float vertexZ, float bFieldInZ,
0220       const std::shared_ptr<const ActsGeometryProvider>& geoSvc, const TrackSeedingConfig& cfg);
0221 
0222 #if TRACKSEEDING_HAS_SEEDING2 || TRACKSEEDING_HAS_SEEDING
0223   // Seeding2-specific: track parameter estimation from space point positions
0224   static std::optional<edm4eic::MutableTrackParameters>
0225   estimateTrackParamsFromSeed(const std::array<std::array<float, 3>, 3>& spPositions, float vertexZ,
0226                               float beamPosX, float beamPosY, float bFieldInZ,
0227                               const std::shared_ptr<const ActsGeometryProvider>& geoSvc,
0228                               const TrackSeedingConfig& cfg);
0229 #endif
0230 
0231 #if TRACKSEEDING_HAS_ORTHOGONAL
0232   // Orthogonal-specific: track parameter estimation from Acts::Seed
0233   std::optional<edm4eic::MutableTrackParameters>
0234   estimateTrackParamsFromSeed(const Acts::Seed<SpacePoint>& seed) const;
0235   static std::vector<const eicrecon::SpacePoint*>
0236   getSpacePoints(const edm4eic::TrackerHitCollection& trk_hits);
0237 #endif
0238 };
0239 } // namespace eicrecon