Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Utilities.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Utilities.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2021 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #pragma once
10 
12 
13 #include <string>
14 #include <unordered_map>
15 
16 #include <boost/preprocessor/seq/for_each.hpp>
17 #include <boost/preprocessor/variadic/to_seq.hpp>
18 #include <pybind11/pybind11.h>
19 
20 namespace Acts::Python {
21 
22 struct Context {
23  std::unordered_map<std::string, pybind11::module_> modules;
24 
25  pybind11::module_& get(const std::string& name) { return modules.at(name); }
26 
27  template <typename... Args, typename = std::enable_if_t<sizeof...(Args) >= 2>>
28  auto get(Args&&... args) {
29  return std::make_tuple((modules.at(args))...);
30  }
31 };
32 
33 template <typename T, typename Ur, typename Ut>
34 void pythonRangeProperty(T& obj, const std::string& name, Ur Ut::*begin,
35  Ur Ut::*end) {
36  obj.def_property(
37  name.c_str(),
38  [=](Ut& self) {
39  return std::pair{self.*begin, self.*end};
40  },
41  [=](Ut& self, std::pair<Ur, Ur> p) {
42  self.*begin = p.first;
43  self.*end = p.second;
44  });
45 }
46 
47 inline void patchClassesWithConfig(pybind11::module_& m) {
48  pybind11::module::import("acts._adapter").attr("_patch_config")(m);
49 }
50 
51 template <typename T>
53  pybind11::module::import("acts._adapter").attr("_patchKwargsConstructor")(c);
54 }
55 
56 METHOD_TRAIT(write_method_trait_t, write);
57 
58 } // namespace Acts::Python
59 
60 #define ACTS_PYTHON_MEMBER(name) \
61  _binding_instance.def_readwrite(#name, &_struct_type::name)
62 
63 #define ACTS_PYTHON_STRUCT_BEGIN(obj, cls) \
64  { \
65  [[maybe_unused]] auto& _binding_instance = obj; \
66  using _struct_type = cls; \
67  do { \
68  } while (0)
69 
70 #define ACTS_PYTHON_STRUCT_END() \
71  } \
72  do { \
73  } while (0)
74 
76 #define ACTS_PYTHON_MEMBER_LOOP(r, data, elem) ACTS_PYTHON_MEMBER(elem);
77 
80 #define ACTS_PYTHON_DECLARE_ALGORITHM(algorithm, mod, name, ...) \
81  do { \
82  using Alg = algorithm; \
83  using Config = Alg::Config; \
84  auto alg = \
85  py::class_<Alg, ActsExamples::IAlgorithm, std::shared_ptr<Alg>>(mod, \
86  name) \
87  .def(py::init<const Config&, Acts::Logging::Level>(), \
88  py::arg("config"), py::arg("level")) \
89  .def_property_readonly("config", &Alg::config); \
90  \
91  auto c = py::class_<Config>(alg, "Config").def(py::init<>()); \
92  ACTS_PYTHON_STRUCT_BEGIN(c, Config); \
93  BOOST_PP_SEQ_FOR_EACH(ACTS_PYTHON_MEMBER_LOOP, _, \
94  BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
95  ACTS_PYTHON_STRUCT_END(); \
96  } while (0)
97 
99 #define ACTS_PYTHON_DECLARE_WRITER(writer, mod, name, ...) \
100  do { \
101  using Writer = writer; \
102  using Config = Writer::Config; \
103  auto w = \
104  py::class_<Writer, ActsExamples::IWriter, std::shared_ptr<Writer>>( \
105  mod, name) \
106  .def(py::init<const Config&, Acts::Logging::Level>(), \
107  py::arg("config"), py::arg("level")) \
108  .def_property_readonly("config", &Writer::config); \
109  \
110  constexpr bool has_write_method = \
111  Acts::Concepts::has_method<Writer, ActsExamples::ProcessCode, \
112  Acts::Python::write_method_trait_t, \
113  const ActsExamples::AlgorithmContext&>; \
114  \
115  if constexpr (has_write_method) { \
116  w.def("write", &Writer::write); \
117  } \
118  \
119  auto c = py::class_<Config>(w, "Config").def(py::init<>()); \
120  ACTS_PYTHON_STRUCT_BEGIN(c, Config); \
121  BOOST_PP_SEQ_FOR_EACH(ACTS_PYTHON_MEMBER_LOOP, _, \
122  BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
123  ACTS_PYTHON_STRUCT_END(); \
124  } while (0)
125 
127 #define ACTS_PYTHON_DECLARE_READER(reader, mod, name, ...) \
128  do { \
129  using Reader = reader; \
130  using Config = Reader::Config; \
131  auto r = \
132  py::class_<Reader, ActsExamples::IReader, std::shared_ptr<Reader>>( \
133  mod, name) \
134  .def(py::init<const Config&, Acts::Logging::Level>(), \
135  py::arg("config"), py::arg("level")) \
136  .def_property_readonly("config", &Reader::config); \
137  \
138  auto c = py::class_<Config>(r, "Config").def(py::init<>()); \
139  ACTS_PYTHON_STRUCT_BEGIN(c, Config); \
140  BOOST_PP_SEQ_FOR_EACH(ACTS_PYTHON_MEMBER_LOOP, _, \
141  BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
142  ACTS_PYTHON_STRUCT_END(); \
143  } while (0)