Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-11 07:50:45

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/Geometry/CylinderVolumeBounds.hpp"
0010 #include "Acts/Geometry/NavigationPolicyFactory.hpp"
0011 #include "Acts/Geometry/TrackingVolume.hpp"
0012 #include "Acts/Navigation/SurfaceArrayNavigationPolicy.hpp"
0013 #include "Acts/Navigation/TryAllNavigationPolicy.hpp"
0014 #include "Acts/Plugins/Python/Utilities.hpp"
0015 #include "Acts/Surfaces/CylinderBounds.hpp"
0016 #include "Acts/Surfaces/CylinderSurface.hpp"
0017 #include "Acts/Utilities/Logger.hpp"
0018 #include "Acts/Utilities/TypeTag.hpp"
0019 
0020 #include <memory>
0021 #include <stdexcept>
0022 #include <utility>
0023 
0024 #include <boost/core/demangle.hpp>
0025 #include <pybind11/pybind11.h>
0026 #include <pybind11/stl.h>
0027 
0028 namespace py = pybind11;
0029 using namespace pybind11::literals;
0030 
0031 namespace Acts::Python {
0032 
0033 struct AnyNavigationPolicyFactory : public Acts::NavigationPolicyFactory {
0034   virtual std::unique_ptr<AnyNavigationPolicyFactory> add(
0035       TypeTag<TryAllNavigationPolicy> /*type*/) = 0;
0036 
0037   virtual std::unique_ptr<AnyNavigationPolicyFactory> add(
0038       TypeTag<SurfaceArrayNavigationPolicy> /*type*/,
0039       SurfaceArrayNavigationPolicy::Config config) = 0;
0040 
0041   virtual std::unique_ptr<AnyNavigationPolicyFactory> add(
0042       TypeTag<TryAllNavigationPolicy> /*type*/,
0043       TryAllNavigationPolicy::Config config) = 0;
0044 };
0045 
0046 template <typename Factory = detail::NavigationPolicyFactoryImpl<>,
0047           typename... Policies>
0048 struct NavigationPolicyFactoryT : public AnyNavigationPolicyFactory {
0049   explicit NavigationPolicyFactoryT(Factory impl)
0050     requires(sizeof...(Policies) > 0)
0051       : m_impl(std::move(impl)) {}
0052 
0053   NavigationPolicyFactoryT()
0054     requires(sizeof...(Policies) == 0)
0055       : m_impl{} {}
0056 
0057   std::unique_ptr<AnyNavigationPolicyFactory> add(
0058       TypeTag<TryAllNavigationPolicy> /*type*/) override {
0059     return add<TryAllNavigationPolicy>();
0060   }
0061 
0062   std::unique_ptr<AnyNavigationPolicyFactory> add(
0063       TypeTag<SurfaceArrayNavigationPolicy> /*type*/,
0064       SurfaceArrayNavigationPolicy::Config config) override {
0065     return add<SurfaceArrayNavigationPolicy>(std::move(config));
0066   }
0067 
0068   std::unique_ptr<AnyNavigationPolicyFactory> add(
0069       TypeTag<TryAllNavigationPolicy> /*type*/,
0070       TryAllNavigationPolicy::Config config) override {
0071     return add<TryAllNavigationPolicy>(config);
0072   }
0073 
0074   std::unique_ptr<INavigationPolicy> build(
0075       const GeometryContext& gctx, const TrackingVolume& volume,
0076       const Logger& logger) const override {
0077     if constexpr (sizeof...(Policies) > 0) {
0078       return m_impl.build(gctx, volume, logger);
0079     } else {
0080       throw std::runtime_error("No policies added to the factory");
0081     }
0082   }
0083 
0084  private:
0085   template <typename T, typename... Args>
0086   std::unique_ptr<AnyNavigationPolicyFactory> add(Args&&... args) {
0087     if constexpr (!(std::is_same_v<T, Policies> || ...)) {
0088       auto impl =
0089           std::move(m_impl).template add<T>(std::forward<Args>(args)...);
0090       return std::make_unique<
0091           NavigationPolicyFactoryT<decltype(impl), Policies..., T>>(
0092           std::move(impl));
0093     } else {
0094       throw std::invalid_argument("Policy already added to the factory");
0095     }
0096   }
0097 
0098   Factory m_impl;
0099 };
0100 
0101 class NavigationPolicyFactory : public Acts::NavigationPolicyFactory {
0102  public:
0103   // This overload is for all the navigation policies that don't have extra
0104   // arguments
0105   NavigationPolicyFactory& addNoArguments(const py::object& cls) {
0106     auto m = py::module_::import("acts");
0107     if (py::object o = m.attr("TryAllNavigationPolicy"); cls.is(o)) {
0108       m_impl = m_impl->add(Type<TryAllNavigationPolicy>);
0109     }
0110     // Add other policies here
0111     return *this;
0112   }
0113 
0114   NavigationPolicyFactory& addSurfaceArray(
0115       const py::object& /*cls*/,
0116       const SurfaceArrayNavigationPolicy::Config& config) {
0117     m_impl = m_impl->add(Type<SurfaceArrayNavigationPolicy>, config);
0118     return *this;
0119   }
0120 
0121   NavigationPolicyFactory& addTryAll(
0122       const py::object& /*cls*/, const TryAllNavigationPolicy::Config& config) {
0123     m_impl = m_impl->add(Type<TryAllNavigationPolicy>, config);
0124     return *this;
0125   }
0126 
0127   std::unique_ptr<INavigationPolicy> build(
0128       const GeometryContext& gctx, const TrackingVolume& volume,
0129       const Logger& logger) const override {
0130     return m_impl->build(gctx, volume, logger);
0131   }
0132 
0133  private:
0134   std::unique_ptr<AnyNavigationPolicyFactory> m_impl =
0135       std::make_unique<NavigationPolicyFactoryT<>>();
0136 };
0137 
0138 namespace Test {
0139 class DetectorElementStub : public DetectorElementBase {
0140  public:
0141   DetectorElementStub() : DetectorElementBase() {}
0142 
0143   const Transform3& transform(const GeometryContext&) const override {
0144     return m_transform;
0145   }
0146 
0147   /// Return surface representation - const return pattern
0148   const Surface& surface() const override {
0149     throw std::runtime_error("Not implemented");
0150   }
0151 
0152   /// Non-const return pattern
0153   Surface& surface() override { throw std::runtime_error("Not implemented"); }
0154 
0155   /// Returns the thickness of the module
0156   /// @return double that indicates the thickness of the module
0157   double thickness() const override { return 0; }
0158 
0159  private:
0160   Transform3 m_transform;
0161 };
0162 
0163 }  // namespace Test
0164 
0165 void addNavigation(Context& ctx) {
0166   auto m = ctx.get("main");
0167 
0168   py::class_<Acts::NavigationPolicyFactory,
0169              std::shared_ptr<Acts::NavigationPolicyFactory>>(
0170       m, "_NavigationPolicyFactory");
0171 
0172   {
0173     auto tryAll =
0174         py::class_<TryAllNavigationPolicy>(m, "TryAllNavigationPolicy");
0175     using Config = TryAllNavigationPolicy::Config;
0176     auto c = py::class_<Config>(tryAll, "Config").def(py::init<>());
0177     ACTS_PYTHON_STRUCT(c, portals, sensitives);
0178   }
0179 
0180   py::class_<NavigationPolicyFactory, Acts::NavigationPolicyFactory,
0181              std::shared_ptr<NavigationPolicyFactory>>(
0182       m, "NavigationPolicyFactory")
0183       // only to mirror the C++ API
0184       .def_static("make", []() { return NavigationPolicyFactory{}; })
0185       .def("add", &NavigationPolicyFactory::addNoArguments)
0186       .def("add", &NavigationPolicyFactory::addSurfaceArray)
0187       .def("add", &NavigationPolicyFactory::addTryAll)
0188       .def("_buildTest", [](NavigationPolicyFactory& self) {
0189         auto vol1 = std::make_shared<TrackingVolume>(
0190             Transform3::Identity(),
0191             std::make_shared<CylinderVolumeBounds>(30, 40, 100));
0192         vol1->setVolumeName("TestVolume");
0193 
0194         auto detElem = std::make_unique<Test::DetectorElementStub>();
0195 
0196         auto surface = Surface::makeShared<CylinderSurface>(
0197             Transform3::Identity(), std::make_shared<CylinderBounds>(30, 40));
0198         surface->assignDetectorElement(*detElem);
0199 
0200         vol1->addSurface(std::move(surface));
0201 
0202         std::unique_ptr<INavigationPolicy> result =
0203             self.build(GeometryContext{}, *vol1,
0204                        *getDefaultLogger("Test", Logging::VERBOSE));
0205       });
0206 
0207   {
0208     auto saPolicy = py::class_<SurfaceArrayNavigationPolicy>(
0209         m, "SurfaceArrayNavigationPolicy");
0210 
0211     using LayerType = SurfaceArrayNavigationPolicy::LayerType;
0212     py::enum_<LayerType>(saPolicy, "LayerType")
0213         .value("Cylinder", LayerType::Cylinder)
0214         .value("Disc", LayerType::Disc)
0215         .value("Plane", LayerType::Plane);
0216 
0217     using Config = SurfaceArrayNavigationPolicy::Config;
0218     auto c = py::class_<Config>(saPolicy, "Config").def(py::init<>());
0219     ACTS_PYTHON_STRUCT(c, layerType, bins);
0220   }
0221 }
0222 
0223 }  // namespace Acts::Python