Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-11 09:40:23

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 #pragma once
0010 
0011 #include "Acts/Utilities/Logger.hpp"
0012 
0013 #include <concepts>
0014 
0015 #include <boost/preprocessor/seq/for_each.hpp>
0016 #include <boost/preprocessor/variadic/to_seq.hpp>
0017 #include <pybind11/pybind11.h>
0018 
0019 namespace ActsExamples {
0020 struct AlgorithmContext;
0021 enum class ProcessCode;
0022 }  // namespace ActsExamples
0023 
0024 namespace ActsPython::Concepts {
0025 template <typename T>
0026 concept has_write_method =
0027     requires(T& t, const ActsExamples::AlgorithmContext& ctx) {
0028       { t.write(ctx) } -> std::same_as<ActsExamples::ProcessCode>;
0029     };
0030 }  // namespace ActsPython::Concepts
0031 
0032 #define ACTS_PYTHON_MEMBER(name) \
0033   _binding_instance.def_readwrite(#name, &_struct_type::name)
0034 
0035 #define ACTS_PYTHON_STRUCT_BEGIN(object)               \
0036   {                                                    \
0037     [[maybe_unused]] auto& _binding_instance = object; \
0038     using _struct_type = decltype(object)::type;       \
0039     do {                                               \
0040     } while (0)
0041 
0042 #define ACTS_PYTHON_STRUCT_END() \
0043   }                              \
0044   do {                           \
0045   } while (0)
0046 
0047 /// This macro is needed to use the BOOST_PP_SEQ_FOR_EACH loop macro
0048 #define ACTS_PYTHON_MEMBER_LOOP(r, data, elem) ACTS_PYTHON_MEMBER(elem);
0049 
0050 /// Macro that accepts a variadic set of member names that are to be registered
0051 /// into an object as read-write fields
0052 #define ACTS_PYTHON_STRUCT(object, ...)                          \
0053   do {                                                           \
0054     ACTS_PYTHON_STRUCT_BEGIN(object);                            \
0055     BOOST_PP_SEQ_FOR_EACH(ACTS_PYTHON_MEMBER_LOOP, _,            \
0056                           BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
0057     ACTS_PYTHON_STRUCT_END();                                    \
0058   } while (0)
0059 
0060 template <typename A, typename B>
0061 auto declareAlgorithm(pybind11::module_& m, const char* name) {
0062   using Config = typename A::Config;
0063   auto alg = pybind11::class_<A, B, std::shared_ptr<A>>(m, name)
0064                  .def(pybind11::init<const Config&, Acts::Logging::Level>(),
0065                       pybind11::arg("config"), pybind11::arg("level"))
0066                  .def_property_readonly("config", &A::config);
0067   auto c = pybind11::class_<Config>(alg, "Config").def(pybind11::init<>());
0068   return std::tuple{alg, c};
0069 }
0070 
0071 /// A macro that uses Boost.Preprocessor to create the python binding for and
0072 /// algorithm and the additional config struct.
0073 #define ACTS_PYTHON_DECLARE_ALGORITHM(algorithm, mod, name, ...)          \
0074   do {                                                                    \
0075     auto [alg, c] =                                                       \
0076         declareAlgorithm<algorithm, ActsExamples::IAlgorithm>(mod, name); \
0077     ACTS_PYTHON_STRUCT(c, __VA_ARGS__);                                   \
0078   } while (0)
0079 
0080 /// Similar as above for writers
0081 #define ACTS_PYTHON_DECLARE_WRITER(writer, mod, name, ...)                  \
0082   do {                                                                      \
0083     using Writer = writer;                                                  \
0084     using Config = Writer::Config;                                          \
0085     auto w =                                                                \
0086         py::class_<Writer, ActsExamples::IWriter, std::shared_ptr<Writer>>( \
0087             mod, name)                                                      \
0088             .def(py::init<const Config&, Acts::Logging::Level>(),           \
0089                  py::arg("config"), py::arg("level"))                       \
0090             .def_property_readonly("config", &Writer::config);              \
0091                                                                             \
0092     constexpr bool has_write_method =                                       \
0093         ActsPython::Concepts::has_write_method<Writer>;                     \
0094                                                                             \
0095     if constexpr (has_write_method) {                                       \
0096       w.def("write", &Writer::write);                                       \
0097     }                                                                       \
0098     auto c = py::class_<Config>(w, "Config").def(py::init<>());             \
0099     ACTS_PYTHON_STRUCT(c, __VA_ARGS__);                                     \
0100   } while (0)
0101 
0102 /// Similar as above for readers
0103 #define ACTS_PYTHON_DECLARE_READER(reader, mod, name, ...)                  \
0104   do {                                                                      \
0105     using Reader = reader;                                                  \
0106     using Config = Reader::Config;                                          \
0107     auto r =                                                                \
0108         py::class_<Reader, ActsExamples::IReader, std::shared_ptr<Reader>>( \
0109             mod, name)                                                      \
0110             .def(py::init<const Config&, Acts::Logging::Level>(),           \
0111                  py::arg("config"), py::arg("level"))                       \
0112             .def_property_readonly("config", &Reader::config);              \
0113                                                                             \
0114     auto c = py::class_<Config>(r, "Config").def(py::init<>());             \
0115     ACTS_PYTHON_STRUCT(c, __VA_ARGS__);                                     \
0116   } while (0)