Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Base.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Base.cpp
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 
16 
17 #include <array>
18 #include <exception>
19 #include <memory>
20 #include <string>
21 #include <unordered_map>
22 
23 #include <pybind11/eval.h>
24 #include <pybind11/pybind11.h>
25 #include <pybind11/stl.h>
26 
27 namespace py = pybind11;
28 using namespace pybind11::literals;
29 
30 namespace Acts::Python {
31 
32 void addUnits(Context& ctx) {
33  auto& m = ctx.get("main");
34  auto u = m.def_submodule("UnitConstants");
35 
36 #define UNIT(x) u.attr(#x) = Acts::UnitConstants::x;
37 
38  UNIT(fm)
39  UNIT(pm)
40  UNIT(um)
41  UNIT(nm)
42  UNIT(mm)
43  UNIT(cm)
44  UNIT(m)
45  UNIT(km)
46  UNIT(mm2)
47  UNIT(cm2)
48  UNIT(m2)
49  UNIT(mm3)
50  UNIT(cm3)
51  UNIT(m3)
52  UNIT(s)
53  UNIT(fs)
54  UNIT(ps)
55  UNIT(ns)
56  UNIT(us)
57  UNIT(ms)
58  UNIT(min)
59  UNIT(h)
60  UNIT(mrad)
61  UNIT(rad)
62  UNIT(degree)
63  UNIT(eV)
64  UNIT(keV)
65  UNIT(MeV)
66  UNIT(GeV)
67  UNIT(TeV)
68  UNIT(J)
69  UNIT(u)
70  UNIT(g)
71  UNIT(kg)
72  UNIT(e)
73  UNIT(T)
74  UNIT(Gauss)
75  UNIT(kGauss)
76  UNIT(mol)
77 
78 #undef UNIT
79 }
80 
81 class PythonLogger {
82  public:
85 
86  void log(Acts::Logging::Level level, const std::string& message) const {
87  m_logger->log(level, message);
88  }
89 
90  void setLevel(Acts::Logging::Level level) {
92  }
93 
94  private:
96  std::unique_ptr<const Logger> m_logger;
97 };
98 
100  auto& m = ctx.get("main");
101  auto logging = m.def_submodule("logging", "");
102 
103  auto levelEnum = py::enum_<Acts::Logging::Level>(logging, "Level")
104  .value("VERBOSE", Acts::Logging::VERBOSE)
105  .value("DEBUG", Acts::Logging::DEBUG)
106  .value("INFO", Acts::Logging::INFO)
107  .value("WARNING", Acts::Logging::WARNING)
108  .value("ERROR", Acts::Logging::ERROR)
109  .value("FATAL", Acts::Logging::FATAL)
110  .value("MAX", Acts::Logging::MAX)
111  .export_values();
112 
113  levelEnum
114  .def("__lt__", [](Acts::Logging::Level self,
115  Acts::Logging::Level other) { return self < other; })
116  .def("__gt__", [](Acts::Logging::Level self,
117  Acts::Logging::Level other) { return self > other; })
118  .def("__le__", [](Acts::Logging::Level self,
119  Acts::Logging::Level other) { return self <= other; })
120  .def("__ge__", [](Acts::Logging::Level self, Acts::Logging::Level other) {
121  return self >= other;
122  });
123 
124  auto makeLogFunction = [](Acts::Logging::Level level) {
125  return
126  [level](PythonLogger& logger, const std::string& fmt, py::args args) {
127  auto locals = py::dict();
128  locals["args"] = args;
129  locals["fmt"] = fmt;
130  py::exec(R"( message = fmt % args )",
131  py::globals(), locals);
132 
133  auto message = locals["message"].cast<std::string>();
134 
135  logger.log(level, message);
136  };
137  };
138 
139  auto logger =
140  py::class_<PythonLogger, std::shared_ptr<PythonLogger>>(logging, "Logger")
141  .def("log", &PythonLogger::log)
142  .def("verbose", makeLogFunction(Acts::Logging::VERBOSE))
143  .def("debug", makeLogFunction(Acts::Logging::DEBUG))
144  .def("info", makeLogFunction(Acts::Logging::INFO))
145  .def("warning", makeLogFunction(Acts::Logging::WARNING))
146  .def("error", makeLogFunction(Acts::Logging::ERROR))
147  .def("fatal", makeLogFunction(Acts::Logging::FATAL))
148  .def("setLevel", &PythonLogger::setLevel);
149 
150  static std::unordered_map<std::string, std::shared_ptr<PythonLogger>>
151  pythonLoggers = {{"root", std::make_shared<PythonLogger>(
152  "Python", Acts::Logging::INFO)}};
153 
154  logging.def(
155  "getLogger",
156  [](const std::string& name) {
157  if (pythonLoggers.find(name) == pythonLoggers.end()) {
158  pythonLoggers[name] =
159  std::make_shared<PythonLogger>(name, Acts::Logging::INFO);
160  }
161  return pythonLoggers[name];
162  },
163  py::arg("name") = "root");
164 
165  logging.def("setLevel", [](Acts::Logging::Level level) {
166  pythonLoggers.at("root")->setLevel(level);
167  });
168 
169  auto makeModuleLogFunction = [](Acts::Logging::Level level) {
170  return [level](const std::string& fmt, py::args args) {
171  auto locals = py::dict();
172  locals["args"] = args;
173  locals["fmt"] = fmt;
174  py::exec(R"( message = fmt % args )",
175  py::globals(), locals);
176 
177  auto message = locals["message"].cast<std::string>();
178 
179  pythonLoggers.at("root")->log(level, message);
180  };
181  };
182 
183  logging.def("setFailureThreshold", &Logging::setFailureThreshold);
184  logging.def("getFailureThreshold", &Logging::getFailureThreshold);
185 
186  static py::exception<Logging::ThresholdFailure> exc(
187  logging, "ThresholdFailure", PyExc_RuntimeError);
188  // NOLINTNEXTLINE(performance-unnecessary-value-param)
189  py::register_exception_translator([](std::exception_ptr p) {
190  try {
191  if (p) {
192  std::rethrow_exception(p);
193  }
194  } catch (const std::exception& e) {
195  std::string what = e.what();
196  if (what.find("ACTS_LOG_FAILURE_THRESHOLD") != std::string::npos) {
197  exc(e.what());
198  } else {
199  std::rethrow_exception(p);
200  }
201  }
202  });
203 
204  logging.def("verbose", makeModuleLogFunction(Acts::Logging::VERBOSE));
205  logging.def("debug", makeModuleLogFunction(Acts::Logging::DEBUG));
206  logging.def("info", makeModuleLogFunction(Acts::Logging::INFO));
207  logging.def("warning", makeModuleLogFunction(Acts::Logging::WARNING));
208  logging.def("error", makeModuleLogFunction(Acts::Logging::ERROR));
209  logging.def("fatal", makeModuleLogFunction(Acts::Logging::FATAL));
210 }
211 
213  auto& m = ctx.get("main");
214  py::enum_<Acts::PdgParticle>(m, "PdgParticle")
215  .value("eInvalid", Acts::PdgParticle::eInvalid)
216  .value("eElectron", Acts::PdgParticle::eElectron)
217  .value("eAntiElectron", Acts::PdgParticle::eAntiElectron)
218  .value("ePositron", Acts::PdgParticle::ePositron)
219  .value("eMuon", Acts::PdgParticle::eMuon)
220  .value("eAntiMuon", Acts::PdgParticle::eAntiMuon)
221  .value("eTau", Acts::PdgParticle::eTau)
222  .value("eAntiTau", Acts::PdgParticle::eAntiTau)
223  .value("eGamma", Acts::PdgParticle::eGamma)
224  .value("ePionZero", Acts::PdgParticle::ePionZero)
225  .value("ePionPlus", Acts::PdgParticle::ePionPlus)
226  .value("ePionMinus", Acts::PdgParticle::ePionMinus)
227  .value("eNeutron", Acts::PdgParticle::eNeutron)
228  .value("eAntiNeutron", Acts::PdgParticle::eAntiNeutron)
229  .value("eProton", Acts::PdgParticle::eProton)
230  .value("eAntiProton", Acts::PdgParticle::eAntiProton)
231  .value("eLead", Acts::PdgParticle::eLead);
232 }
233 
235  auto& m = ctx.get("main");
236 
237  py::class_<Acts::Vector2>(m, "Vector2")
238  .def(py::init<double, double>())
239  .def(py::init([](std::array<double, 2> a) {
241  v << a[0], a[1];
242  return v;
243  }))
244  .def("__getitem__",
245  [](const Acts::Vector2& self, Eigen::Index i) { return self[i]; });
246 
247  py::class_<Acts::Vector3>(m, "Vector3")
248  .def(py::init<double, double, double>())
249  .def(py::init([](std::array<double, 3> a) {
251  v << a[0], a[1], a[2];
252  return v;
253  }))
254  .def("__getitem__",
255  [](const Acts::Vector3& self, Eigen::Index i) { return self[i]; });
256 
257  py::class_<Acts::Vector4>(m, "Vector4")
258  .def(py::init<double, double, double, double>())
259  .def(py::init([](std::array<double, 4> a) {
261  v << a[0], a[1], a[2], a[3];
262  return v;
263  }))
264  .def("__getitem__",
265  [](const Acts::Vector4& self, Eigen::Index i) { return self[i]; });
266 
267  py::class_<Acts::Transform3>(m, "Transform3")
268  .def(py::init([](std::array<double, 3> translation) {
269  Acts::Transform3 t = Acts::Transform3::Identity();
270  t.pretranslate(
271  Acts::Vector3(translation[0], translation[1], translation[2]));
272  return t;
273  }))
274  .def("getTranslation", [](const Acts::Transform3& self) {
275  return Vector3(self.translation());
276  });
277 }
278 
279 void addBinning(Context& ctx) {
280  auto& m = ctx.get("main");
281  auto binning = m.def_submodule("Binning", "");
282 
283  auto binningValue = py::enum_<Acts::BinningValue>(binning, "BinningValue")
285  .value("y", Acts::BinningValue::binY)
286  .value("z", Acts::BinningValue::binZ)
287  .value("r", Acts::BinningValue::binR)
288  .value("phi", Acts::BinningValue::binPhi)
289  .export_values();
290 
291  auto boundaryType =
292  py::enum_<Acts::detail::AxisBoundaryType>(binning, "AxisBoundaryType")
293  .value("bound", Acts::detail::AxisBoundaryType::Bound)
294  .value("closed", Acts::detail::AxisBoundaryType::Closed)
295  .value("open", Acts::detail::AxisBoundaryType::Open)
296  .export_values();
297 
298  auto axisType = py::enum_<Acts::detail::AxisType>(binning, "AxisType")
299  .value("equidistant", Acts::detail::AxisType::Equidistant)
300  .value("variable", Acts::detail::AxisType::Variable)
301  .export_values();
302 }
303 
304 } // namespace Acts::Python
305