Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:10:04

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2021 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 http://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/Plugins/Python/Utilities.hpp"
0013 #include "Acts/Utilities/BinningData.hpp"
0014 #include "Acts/Utilities/Logger.hpp"
0015 #include "Acts/Utilities/detail/AxisFwd.hpp"
0016 
0017 #include <array>
0018 #include <exception>
0019 #include <memory>
0020 #include <string>
0021 #include <unordered_map>
0022 
0023 #include <pybind11/eval.h>
0024 #include <pybind11/pybind11.h>
0025 #include <pybind11/stl.h>
0026 
0027 namespace py = pybind11;
0028 using namespace pybind11::literals;
0029 
0030 namespace Acts::Python {
0031 
0032 void addUnits(Context& ctx) {
0033   auto& m = ctx.get("main");
0034   auto u = m.def_submodule("UnitConstants");
0035 
0036 #define UNIT(x) u.attr(#x) = Acts::UnitConstants::x;
0037 
0038   UNIT(fm)
0039   UNIT(pm)
0040   UNIT(um)
0041   UNIT(nm)
0042   UNIT(mm)
0043   UNIT(cm)
0044   UNIT(m)
0045   UNIT(km)
0046   UNIT(mm2)
0047   UNIT(cm2)
0048   UNIT(m2)
0049   UNIT(mm3)
0050   UNIT(cm3)
0051   UNIT(m3)
0052   UNIT(s)
0053   UNIT(fs)
0054   UNIT(ps)
0055   UNIT(ns)
0056   UNIT(us)
0057   UNIT(ms)
0058   UNIT(min)
0059   UNIT(h)
0060   UNIT(mrad)
0061   UNIT(rad)
0062   UNIT(degree)
0063   UNIT(eV)
0064   UNIT(keV)
0065   UNIT(MeV)
0066   UNIT(GeV)
0067   UNIT(TeV)
0068   UNIT(J)
0069   UNIT(u)
0070   UNIT(g)
0071   UNIT(kg)
0072   UNIT(e)
0073   UNIT(T)
0074   UNIT(Gauss)
0075   UNIT(kGauss)
0076   UNIT(mol)
0077 
0078 #undef UNIT
0079 }
0080 
0081 class PythonLogger {
0082  public:
0083   PythonLogger(const std::string& name, Acts::Logging::Level level)
0084       : m_name{name}, m_logger{Acts::getDefaultLogger(m_name, level)} {}
0085 
0086   void log(Acts::Logging::Level level, const std::string& message) const {
0087     m_logger->log(level, message);
0088   }
0089 
0090   void setLevel(Acts::Logging::Level level) {
0091     m_logger = Acts::getDefaultLogger(m_name, level);
0092   }
0093 
0094  private:
0095   std::string m_name;
0096   std::unique_ptr<const Logger> m_logger;
0097 };
0098 
0099 void addLogging(Acts::Python::Context& ctx) {
0100   auto& m = ctx.get("main");
0101   auto logging = m.def_submodule("logging", "");
0102 
0103   auto levelEnum = py::enum_<Acts::Logging::Level>(logging, "Level")
0104                        .value("VERBOSE", Acts::Logging::VERBOSE)
0105                        .value("DEBUG", Acts::Logging::DEBUG)
0106                        .value("INFO", Acts::Logging::INFO)
0107                        .value("WARNING", Acts::Logging::WARNING)
0108                        .value("ERROR", Acts::Logging::ERROR)
0109                        .value("FATAL", Acts::Logging::FATAL)
0110                        .value("MAX", Acts::Logging::MAX)
0111                        .export_values();
0112 
0113   levelEnum
0114       .def("__lt__", [](Acts::Logging::Level self,
0115                         Acts::Logging::Level other) { return self < other; })
0116       .def("__gt__", [](Acts::Logging::Level self,
0117                         Acts::Logging::Level other) { return self > other; })
0118       .def("__le__", [](Acts::Logging::Level self,
0119                         Acts::Logging::Level other) { return self <= other; })
0120       .def("__ge__", [](Acts::Logging::Level self, Acts::Logging::Level other) {
0121         return self >= other;
0122       });
0123 
0124   auto makeLogFunction = [](Acts::Logging::Level level) {
0125     return
0126         [level](PythonLogger& logger, const std::string& fmt, py::args args) {
0127           auto locals = py::dict();
0128           locals["args"] = args;
0129           locals["fmt"] = fmt;
0130           py::exec(R"(
0131         message = fmt % args
0132     )",
0133                    py::globals(), locals);
0134 
0135           auto message = locals["message"].cast<std::string>();
0136 
0137           logger.log(level, message);
0138         };
0139   };
0140 
0141   auto logger =
0142       py::class_<PythonLogger, std::shared_ptr<PythonLogger>>(logging, "Logger")
0143           .def("log", &PythonLogger::log)
0144           .def("verbose", makeLogFunction(Acts::Logging::VERBOSE))
0145           .def("debug", makeLogFunction(Acts::Logging::DEBUG))
0146           .def("info", makeLogFunction(Acts::Logging::INFO))
0147           .def("warning", makeLogFunction(Acts::Logging::WARNING))
0148           .def("error", makeLogFunction(Acts::Logging::ERROR))
0149           .def("fatal", makeLogFunction(Acts::Logging::FATAL))
0150           .def("setLevel", &PythonLogger::setLevel);
0151 
0152   static std::unordered_map<std::string, std::shared_ptr<PythonLogger>>
0153       pythonLoggers = {{"root", std::make_shared<PythonLogger>(
0154                                     "Python", Acts::Logging::INFO)}};
0155 
0156   logging.def(
0157       "getLogger",
0158       [](const std::string& name) {
0159         if (pythonLoggers.find(name) == pythonLoggers.end()) {
0160           pythonLoggers[name] =
0161               std::make_shared<PythonLogger>(name, Acts::Logging::INFO);
0162         }
0163         return pythonLoggers[name];
0164       },
0165       py::arg("name") = "root");
0166 
0167   logging.def("setLevel", [](Acts::Logging::Level level) {
0168     pythonLoggers.at("root")->setLevel(level);
0169   });
0170 
0171   auto makeModuleLogFunction = [](Acts::Logging::Level level) {
0172     return [level](const std::string& fmt, py::args args) {
0173       auto locals = py::dict();
0174       locals["args"] = args;
0175       locals["fmt"] = fmt;
0176       py::exec(R"(
0177         message = fmt % args
0178     )",
0179                py::globals(), locals);
0180 
0181       auto message = locals["message"].cast<std::string>();
0182 
0183       pythonLoggers.at("root")->log(level, message);
0184     };
0185   };
0186 
0187   logging.def("setFailureThreshold", &Logging::setFailureThreshold);
0188   logging.def("getFailureThreshold", &Logging::getFailureThreshold);
0189 
0190   static py::exception<Logging::ThresholdFailure> exc(
0191       logging, "ThresholdFailure", PyExc_RuntimeError);
0192   // NOLINTNEXTLINE(performance-unnecessary-value-param)
0193   py::register_exception_translator([](std::exception_ptr p) {
0194     try {
0195       if (p) {
0196         std::rethrow_exception(p);
0197       }
0198     } catch (const std::exception& e) {
0199       std::string what = e.what();
0200       if (what.find("ACTS_LOG_FAILURE_THRESHOLD") != std::string::npos) {
0201         exc(e.what());
0202       } else {
0203         std::rethrow_exception(p);
0204       }
0205     }
0206   });
0207 
0208   logging.def("verbose", makeModuleLogFunction(Acts::Logging::VERBOSE));
0209   logging.def("debug", makeModuleLogFunction(Acts::Logging::DEBUG));
0210   logging.def("info", makeModuleLogFunction(Acts::Logging::INFO));
0211   logging.def("warning", makeModuleLogFunction(Acts::Logging::WARNING));
0212   logging.def("error", makeModuleLogFunction(Acts::Logging::ERROR));
0213   logging.def("fatal", makeModuleLogFunction(Acts::Logging::FATAL));
0214 }
0215 
0216 void addPdgParticle(Acts::Python::Context& ctx) {
0217   auto& m = ctx.get("main");
0218   py::enum_<Acts::PdgParticle>(m, "PdgParticle")
0219       .value("eInvalid", Acts::PdgParticle::eInvalid)
0220       .value("eElectron", Acts::PdgParticle::eElectron)
0221       .value("eAntiElectron", Acts::PdgParticle::eAntiElectron)
0222       .value("ePositron", Acts::PdgParticle::ePositron)
0223       .value("eMuon", Acts::PdgParticle::eMuon)
0224       .value("eAntiMuon", Acts::PdgParticle::eAntiMuon)
0225       .value("eTau", Acts::PdgParticle::eTau)
0226       .value("eAntiTau", Acts::PdgParticle::eAntiTau)
0227       .value("eGamma", Acts::PdgParticle::eGamma)
0228       .value("ePionZero", Acts::PdgParticle::ePionZero)
0229       .value("ePionPlus", Acts::PdgParticle::ePionPlus)
0230       .value("ePionMinus", Acts::PdgParticle::ePionMinus)
0231       .value("eKaonPlus", Acts::PdgParticle::eKaonPlus)
0232       .value("eKaonMinus", Acts::PdgParticle::eKaonMinus)
0233       .value("eNeutron", Acts::PdgParticle::eNeutron)
0234       .value("eAntiNeutron", Acts::PdgParticle::eAntiNeutron)
0235       .value("eProton", Acts::PdgParticle::eProton)
0236       .value("eAntiProton", Acts::PdgParticle::eAntiProton)
0237       .value("eLead", Acts::PdgParticle::eLead);
0238 }
0239 
0240 void addAlgebra(Acts::Python::Context& ctx) {
0241   auto& m = ctx.get("main");
0242 
0243   py::class_<Acts::Vector2>(m, "Vector2")
0244       .def(py::init<double, double>())
0245       .def(py::init([](std::array<double, 2> a) {
0246         Acts::Vector2 v;
0247         v << a[0], a[1];
0248         return v;
0249       }))
0250       .def("__getitem__",
0251            [](const Acts::Vector2& self, Eigen::Index i) { return self[i]; });
0252 
0253   py::class_<Acts::Vector3>(m, "Vector3")
0254       .def(py::init<double, double, double>())
0255       .def(py::init([](std::array<double, 3> a) {
0256         Acts::Vector3 v;
0257         v << a[0], a[1], a[2];
0258         return v;
0259       }))
0260       .def("__getitem__",
0261            [](const Acts::Vector3& self, Eigen::Index i) { return self[i]; });
0262 
0263   py::class_<Acts::Vector4>(m, "Vector4")
0264       .def(py::init<double, double, double, double>())
0265       .def(py::init([](std::array<double, 4> a) {
0266         Acts::Vector4 v;
0267         v << a[0], a[1], a[2], a[3];
0268         return v;
0269       }))
0270       .def("__getitem__",
0271            [](const Acts::Vector4& self, Eigen::Index i) { return self[i]; });
0272 
0273   py::class_<Acts::Transform3>(m, "Transform3")
0274       .def(py::init([](std::array<double, 3> translation) {
0275         Acts::Transform3 t = Acts::Transform3::Identity();
0276         t.pretranslate(
0277             Acts::Vector3(translation[0], translation[1], translation[2]));
0278         return t;
0279       }))
0280       .def("getTranslation", [](const Acts::Transform3& self) {
0281         return Vector3(self.translation());
0282       });
0283 }
0284 
0285 void addBinning(Context& ctx) {
0286   auto& m = ctx.get("main");
0287   auto binning = m.def_submodule("Binning", "");
0288 
0289   auto binningValue = py::enum_<Acts::BinningValue>(binning, "BinningValue")
0290                           .value("x", Acts::BinningValue::binX)
0291                           .value("y", Acts::BinningValue::binY)
0292                           .value("z", Acts::BinningValue::binZ)
0293                           .value("r", Acts::BinningValue::binR)
0294                           .value("phi", Acts::BinningValue::binPhi)
0295                           .export_values();
0296 
0297   auto boundaryType =
0298       py::enum_<Acts::detail::AxisBoundaryType>(binning, "AxisBoundaryType")
0299           .value("bound", Acts::detail::AxisBoundaryType::Bound)
0300           .value("closed", Acts::detail::AxisBoundaryType::Closed)
0301           .value("open", Acts::detail::AxisBoundaryType::Open)
0302           .export_values();
0303 
0304   auto axisType = py::enum_<Acts::detail::AxisType>(binning, "AxisType")
0305                       .value("equidistant", Acts::detail::AxisType::Equidistant)
0306                       .value("variable", Acts::detail::AxisType::Variable)
0307                       .export_values();
0308 }
0309 
0310 }  // namespace Acts::Python