File indexing completed on 2025-01-18 09:12:01
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Definitions/Algebra.hpp"
0010 #include "Acts/Definitions/PdgParticle.hpp"
0011 #include "Acts/Definitions/Units.hpp"
0012 #include "Acts/Geometry/GeometryContext.hpp"
0013 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0014 #include "Acts/Plugins/Python/Utilities.hpp"
0015 #include "Acts/Utilities/Any.hpp"
0016 #include "Acts/Utilities/AxisDefinitions.hpp"
0017 #include "Acts/Utilities/BinningData.hpp"
0018 #include "Acts/Utilities/CalibrationContext.hpp"
0019 #include "Acts/Utilities/Logger.hpp"
0020
0021 #include <array>
0022 #include <exception>
0023 #include <memory>
0024 #include <string>
0025 #include <unordered_map>
0026
0027 #include <pybind11/eval.h>
0028 #include <pybind11/pybind11.h>
0029 #include <pybind11/pytypes.h>
0030 #include <pybind11/stl.h>
0031
0032 namespace py = pybind11;
0033 using namespace pybind11::literals;
0034
0035 namespace Acts::Python {
0036
0037 void addContext(Context& ctx) {
0038 auto& m = ctx.get("main");
0039
0040 py::class_<Acts::GeometryContext>(m, "GeometryContext").def(py::init<>());
0041 py::class_<Acts::MagneticFieldContext>(m, "MagneticFieldContext")
0042 .def(py::init<>());
0043 py::class_<Acts::CalibrationContext>(m, "CalibrationContext")
0044 .def(py::init<>());
0045 }
0046
0047 void addAny(Context& ctx) {
0048 auto& m = ctx.get("main");
0049
0050 py::class_<Acts::AnyBase<512>>(m, "AnyBase512").def(py::init<>());
0051 }
0052
0053 void addUnits(Context& ctx) {
0054 auto& m = ctx.get("main");
0055 auto u = m.def_submodule("UnitConstants");
0056
0057 #define UNIT(x) u.attr(#x) = Acts::UnitConstants::x;
0058
0059 UNIT(fm)
0060 UNIT(pm)
0061 UNIT(um)
0062 UNIT(nm)
0063 UNIT(mm)
0064 UNIT(cm)
0065 UNIT(m)
0066 UNIT(km)
0067 UNIT(mm2)
0068 UNIT(cm2)
0069 UNIT(m2)
0070 UNIT(mm3)
0071 UNIT(cm3)
0072 UNIT(m3)
0073 UNIT(s)
0074 UNIT(fs)
0075 UNIT(ps)
0076 UNIT(ns)
0077 UNIT(us)
0078 UNIT(ms)
0079 UNIT(min)
0080 UNIT(h)
0081 UNIT(mrad)
0082 UNIT(rad)
0083 UNIT(degree)
0084 UNIT(eV)
0085 UNIT(keV)
0086 UNIT(MeV)
0087 UNIT(GeV)
0088 UNIT(TeV)
0089 UNIT(J)
0090 UNIT(u)
0091 UNIT(g)
0092 UNIT(kg)
0093 UNIT(e)
0094 UNIT(T)
0095 UNIT(Gauss)
0096 UNIT(kGauss)
0097 UNIT(mol)
0098
0099 #undef UNIT
0100 }
0101
0102 class PythonLogger {
0103 public:
0104 PythonLogger(const std::string& name, Acts::Logging::Level level)
0105 : m_name{name}, m_logger{Acts::getDefaultLogger(m_name, level)} {}
0106
0107 void log(Acts::Logging::Level level, const std::string& message) const {
0108 m_logger->log(level, message);
0109 }
0110
0111 void setLevel(Acts::Logging::Level level) {
0112 m_logger = Acts::getDefaultLogger(m_name, level);
0113 }
0114
0115 private:
0116 std::string m_name;
0117 std::unique_ptr<const Logger> m_logger;
0118 };
0119
0120 void addLogging(Acts::Python::Context& ctx) {
0121 auto& m = ctx.get("main");
0122 auto logging = m.def_submodule("logging", "");
0123
0124 auto levelEnum = py::enum_<Acts::Logging::Level>(logging, "Level")
0125 .value("VERBOSE", Acts::Logging::VERBOSE)
0126 .value("DEBUG", Acts::Logging::DEBUG)
0127 .value("INFO", Acts::Logging::INFO)
0128 .value("WARNING", Acts::Logging::WARNING)
0129 .value("ERROR", Acts::Logging::ERROR)
0130 .value("FATAL", Acts::Logging::FATAL)
0131 .value("MAX", Acts::Logging::MAX)
0132 .export_values();
0133
0134 levelEnum
0135 .def("__lt__", [](Acts::Logging::Level self,
0136 Acts::Logging::Level other) { return self < other; })
0137 .def("__gt__", [](Acts::Logging::Level self,
0138 Acts::Logging::Level other) { return self > other; })
0139 .def("__le__", [](Acts::Logging::Level self,
0140 Acts::Logging::Level other) { return self <= other; })
0141 .def("__ge__", [](Acts::Logging::Level self, Acts::Logging::Level other) {
0142 return self >= other;
0143 });
0144
0145 auto makeLogFunction = [](Acts::Logging::Level level) {
0146 return
0147 [level](PythonLogger& logger, const std::string& fmt, py::args args) {
0148 auto locals = py::dict();
0149 locals["args"] = args;
0150 locals["fmt"] = fmt;
0151 py::exec(R"(
0152 message = fmt % args
0153 )",
0154 py::globals(), locals);
0155
0156 auto message = locals["message"].cast<std::string>();
0157
0158 logger.log(level, message);
0159 };
0160 };
0161
0162 auto logger =
0163 py::class_<PythonLogger, std::shared_ptr<PythonLogger>>(logging, "Logger")
0164 .def("log", &PythonLogger::log)
0165 .def("verbose", makeLogFunction(Acts::Logging::VERBOSE))
0166 .def("debug", makeLogFunction(Acts::Logging::DEBUG))
0167 .def("info", makeLogFunction(Acts::Logging::INFO))
0168 .def("warning", makeLogFunction(Acts::Logging::WARNING))
0169 .def("error", makeLogFunction(Acts::Logging::ERROR))
0170 .def("fatal", makeLogFunction(Acts::Logging::FATAL))
0171 .def("setLevel", &PythonLogger::setLevel);
0172
0173 static std::unordered_map<std::string, std::shared_ptr<PythonLogger>>
0174 pythonLoggers = {{"root", std::make_shared<PythonLogger>(
0175 "Python", Acts::Logging::INFO)}};
0176
0177 logging.def(
0178 "getLogger",
0179 [](const std::string& name) {
0180 if (!pythonLoggers.contains(name)) {
0181 pythonLoggers[name] =
0182 std::make_shared<PythonLogger>(name, Acts::Logging::INFO);
0183 }
0184 return pythonLoggers[name];
0185 },
0186 py::arg("name") = "root");
0187
0188 logging.def("setLevel", [](Acts::Logging::Level level) {
0189 pythonLoggers.at("root")->setLevel(level);
0190 });
0191
0192 auto makeModuleLogFunction = [](Acts::Logging::Level level) {
0193 return [level](const std::string& fmt, py::args args) {
0194 auto locals = py::dict();
0195 locals["args"] = args;
0196 locals["fmt"] = fmt;
0197 py::exec(R"(
0198 message = fmt % args
0199 )",
0200 py::globals(), locals);
0201
0202 auto message = locals["message"].cast<std::string>();
0203
0204 pythonLoggers.at("root")->log(level, message);
0205 };
0206 };
0207
0208 logging.def("setFailureThreshold", &Logging::setFailureThreshold);
0209 logging.def("getFailureThreshold", &Logging::getFailureThreshold);
0210
0211 static py::exception<Logging::ThresholdFailure> exc(
0212 logging, "ThresholdFailure", PyExc_RuntimeError);
0213
0214 py::register_exception_translator([](std::exception_ptr p) {
0215 try {
0216 if (p) {
0217 std::rethrow_exception(p);
0218 }
0219 } catch (const std::exception& e) {
0220 std::string what = e.what();
0221 if (what.find("ACTS_LOG_FAILURE_THRESHOLD") != std::string::npos) {
0222 py::set_error(exc, e.what());
0223 } else {
0224 std::rethrow_exception(p);
0225 }
0226 }
0227 });
0228
0229 logging.def("verbose", makeModuleLogFunction(Acts::Logging::VERBOSE));
0230 logging.def("debug", makeModuleLogFunction(Acts::Logging::DEBUG));
0231 logging.def("info", makeModuleLogFunction(Acts::Logging::INFO));
0232 logging.def("warning", makeModuleLogFunction(Acts::Logging::WARNING));
0233 logging.def("error", makeModuleLogFunction(Acts::Logging::ERROR));
0234 logging.def("fatal", makeModuleLogFunction(Acts::Logging::FATAL));
0235 }
0236
0237 void addPdgParticle(Acts::Python::Context& ctx) {
0238 auto& m = ctx.get("main");
0239 py::enum_<Acts::PdgParticle>(m, "PdgParticle")
0240 .value("eInvalid", Acts::PdgParticle::eInvalid)
0241 .value("eElectron", Acts::PdgParticle::eElectron)
0242 .value("eAntiElectron", Acts::PdgParticle::eAntiElectron)
0243 .value("ePositron", Acts::PdgParticle::ePositron)
0244 .value("eMuon", Acts::PdgParticle::eMuon)
0245 .value("eAntiMuon", Acts::PdgParticle::eAntiMuon)
0246 .value("eTau", Acts::PdgParticle::eTau)
0247 .value("eAntiTau", Acts::PdgParticle::eAntiTau)
0248 .value("eGamma", Acts::PdgParticle::eGamma)
0249 .value("ePionZero", Acts::PdgParticle::ePionZero)
0250 .value("ePionPlus", Acts::PdgParticle::ePionPlus)
0251 .value("ePionMinus", Acts::PdgParticle::ePionMinus)
0252 .value("eKaonPlus", Acts::PdgParticle::eKaonPlus)
0253 .value("eKaonMinus", Acts::PdgParticle::eKaonMinus)
0254 .value("eNeutron", Acts::PdgParticle::eNeutron)
0255 .value("eAntiNeutron", Acts::PdgParticle::eAntiNeutron)
0256 .value("eProton", Acts::PdgParticle::eProton)
0257 .value("eAntiProton", Acts::PdgParticle::eAntiProton)
0258 .value("eLead", Acts::PdgParticle::eLead);
0259 }
0260
0261 void addAlgebra(Acts::Python::Context& ctx) {
0262 auto& m = ctx.get("main");
0263
0264 py::class_<Acts::Vector2>(m, "Vector2")
0265 .def(py::init<double, double>())
0266 .def(py::init([](std::array<double, 2> a) {
0267 Acts::Vector2 v;
0268 v << a[0], a[1];
0269 return v;
0270 }))
0271 .def("__getitem__",
0272 [](const Acts::Vector2& self, Eigen::Index i) { return self[i]; })
0273 .def("__str__", [](const Acts::Vector3& self) {
0274 std::stringstream ss;
0275 ss << self.transpose();
0276 return ss.str();
0277 });
0278
0279 py::class_<Acts::Vector3>(m, "Vector3")
0280 .def(py::init<double, double, double>())
0281 .def(py::init([](std::array<double, 3> a) {
0282 Acts::Vector3 v;
0283 v << a[0], a[1], a[2];
0284 return v;
0285 }))
0286 .def_static("UnitX", []() -> Vector3 { return Acts::Vector3::UnitX(); })
0287 .def_static("UnitY", []() -> Vector3 { return Acts::Vector3::UnitY(); })
0288 .def_static("UnitZ", []() -> Vector3 { return Acts::Vector3::UnitZ(); })
0289
0290 .def("__getitem__",
0291 [](const Acts::Vector3& self, Eigen::Index i) { return self[i]; })
0292 .def("__str__", [](const Acts::Vector3& self) {
0293 std::stringstream ss;
0294 ss << self.transpose();
0295 return ss.str();
0296 });
0297
0298 py::class_<Acts::Vector4>(m, "Vector4")
0299 .def(py::init<double, double, double, double>())
0300 .def(py::init([](std::array<double, 4> a) {
0301 Acts::Vector4 v;
0302 v << a[0], a[1], a[2], a[3];
0303 return v;
0304 }))
0305 .def("__getitem__",
0306 [](const Acts::Vector4& self, Eigen::Index i) { return self[i]; });
0307
0308 py::class_<Acts::Transform3>(m, "Transform3")
0309 .def(py::init<>())
0310 .def(py::init([](const Vector3& translation) -> Transform3 {
0311 return Transform3{Translation3{translation}};
0312 }))
0313 .def_property_readonly("translation",
0314 [](const Acts::Transform3& self) -> Vector3 {
0315 return self.translation();
0316 })
0317 .def_static("Identity", &Acts::Transform3::Identity)
0318 .def("__mul__",
0319 [](const Acts::Transform3& self, const Acts::Transform3& other) {
0320 return self * other;
0321 })
0322 .def("__mul__",
0323 [](const Acts::Transform3& self, const Acts::Translation3& other) {
0324 return self * other;
0325 })
0326 .def("__mul__",
0327 [](const Acts::Transform3& self, const Acts::AngleAxis3& other) {
0328 return self * other;
0329 })
0330 .def("__str__", [](const Acts::Transform3& self) {
0331 std::stringstream ss;
0332 ss << self.matrix();
0333 return ss.str();
0334 });
0335
0336 py::class_<Acts::Translation3>(m, "Translation3")
0337 .def(py::init(
0338 [](const Acts::Vector3& a) { return Acts::Translation3(a); }))
0339 .def(py::init([](std::array<double, 3> a) {
0340 return Acts::Translation3(Acts::Vector3(a[0], a[1], a[2]));
0341 }))
0342 .def("__str__", [](const Acts::Translation3& self) {
0343 std::stringstream ss;
0344 ss << self.translation().transpose();
0345 return ss.str();
0346 });
0347
0348 py::class_<Acts::AngleAxis3>(m, "AngleAxis3")
0349 .def(py::init([](double angle, const Acts::Vector3& axis) {
0350 return Acts::AngleAxis3(angle, axis);
0351 }))
0352 .def("__str__", [](const Acts::Transform3& self) {
0353 std::stringstream ss;
0354 ss << self.matrix();
0355 return ss.str();
0356 });
0357 }
0358
0359 void addBinning(Context& ctx) {
0360 auto& m = ctx.get("main");
0361
0362 auto binningValue = py::enum_<Acts::AxisDirection>(m, "AxisDirection")
0363 .value("AxisX", Acts::AxisDirection::AxisX)
0364 .value("AxisY", Acts::AxisDirection::AxisY)
0365 .value("AxisZ", Acts::AxisDirection::AxisZ)
0366 .value("AxisR", Acts::AxisDirection::AxisR)
0367 .value("AxisPhi", Acts::AxisDirection::AxisPhi)
0368 .value("AxisRPhi", Acts::AxisDirection::AxisRPhi)
0369 .value("AxisTheta", Acts::AxisDirection::AxisTheta)
0370 .value("AxisEta", Acts::AxisDirection::AxisEta)
0371 .value("AxisMag", Acts::AxisDirection::AxisMag);
0372
0373 auto boundaryType = py::enum_<Acts::AxisBoundaryType>(m, "AxisBoundaryType")
0374 .value("Bound", Acts::AxisBoundaryType::Bound)
0375 .value("Closed", Acts::AxisBoundaryType::Closed)
0376 .value("Open", Acts::AxisBoundaryType::Open);
0377
0378 auto axisType = py::enum_<Acts::AxisType>(m, "AxisType")
0379 .value("equidistant", Acts::AxisType::Equidistant)
0380 .value("variable", Acts::AxisType::Variable);
0381 }
0382
0383 }