Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:12:01

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/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   // NOLINTNEXTLINE(performance-unnecessary-value-param)
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 }  // namespace Acts::Python