Warning, file /acts/Examples/Python/src/Framework.cpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Plugins/Python/Utilities.hpp"
0010 #include "ActsExamples/Framework/AlgorithmContext.hpp"
0011 #include "ActsExamples/Framework/IAlgorithm.hpp"
0012 #include "ActsExamples/Framework/IReader.hpp"
0013 #include "ActsExamples/Framework/IWriter.hpp"
0014 #include "ActsExamples/Framework/ProcessCode.hpp"
0015 #include "ActsExamples/Framework/RandomNumbers.hpp"
0016 #include "ActsExamples/Framework/SequenceElement.hpp"
0017 #include "ActsExamples/Framework/Sequencer.hpp"
0018 #include "ActsExamples/Framework/WhiteBoard.hpp"
0019
0020 #include <pybind11/pybind11.h>
0021 #include <pybind11/stl.h>
0022
0023 namespace py = pybind11;
0024 using namespace py::literals;
0025 using namespace ActsExamples;
0026 using namespace Acts::Python;
0027
0028 namespace {
0029 #if defined(__clang__)
0030 #pragma clang diagnostic push
0031 #pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
0032 #endif
0033 class PySequenceElement : public SequenceElement {
0034 public:
0035 using SequenceElement::SequenceElement;
0036
0037 std::string name() const override {
0038 py::gil_scoped_acquire acquire{};
0039 PYBIND11_OVERRIDE_PURE(std::string, SequenceElement, name);
0040 }
0041
0042 ProcessCode internalExecute(const AlgorithmContext& ctx) override {
0043 py::gil_scoped_acquire acquire{};
0044 PYBIND11_OVERRIDE_PURE(ProcessCode, SequenceElement, sysExecute, ctx);
0045 }
0046
0047 ProcessCode initialize() override {
0048 py::gil_scoped_acquire acquire{};
0049 PYBIND11_OVERRIDE_PURE(ProcessCode, SequenceElement, initialize);
0050 }
0051
0052 ProcessCode finalize() override {
0053 py::gil_scoped_acquire acquire{};
0054 PYBIND11_OVERRIDE_PURE(ProcessCode, SequenceElement, finalize);
0055 }
0056 };
0057 #if defined(__clang__)
0058 #pragma clang diagnostic pop
0059 #endif
0060
0061 class PyIAlgorithm : public IAlgorithm {
0062 public:
0063 using IAlgorithm::IAlgorithm;
0064
0065 ProcessCode execute(const AlgorithmContext& ctx) const override {
0066 py::gil_scoped_acquire acquire{};
0067 try {
0068 PYBIND11_OVERRIDE_PURE(ProcessCode, IAlgorithm, execute, ctx);
0069 } catch (py::error_already_set& e) {
0070 throw;
0071 } catch (std::runtime_error& e) {
0072 throw py::type_error("Python algorithm did not conform to interface");
0073 }
0074 }
0075
0076 std::string_view typeName() const override { return "Algorithm"; }
0077 };
0078
0079 void trigger_divbyzero() {
0080 volatile float j = 0.0;
0081 volatile float r = 123 / j;
0082 (void)r;
0083 }
0084
0085 void trigger_overflow() {
0086 volatile float j = std::numeric_limits<float>::max();
0087 volatile float r = j * j;
0088 (void)r;
0089 }
0090
0091 void trigger_invalid() {
0092 volatile float j = -1;
0093 volatile float r = std::sqrt(j);
0094 (void)r;
0095 }
0096
0097 }
0098
0099 namespace Acts::Python {
0100 void addFramework(Context& ctx) {
0101 auto [m, mex] = ctx.get("main", "examples");
0102
0103 py::class_<ActsExamples::IWriter, std::shared_ptr<ActsExamples::IWriter>>(
0104 mex, "IWriter");
0105
0106 py::class_<ActsExamples::IReader, std::shared_ptr<ActsExamples::IReader>>(
0107 mex, "IReader");
0108
0109 py::class_<ActsExamples::IContextDecorator,
0110 std::shared_ptr<ActsExamples::IContextDecorator>>(
0111 mex, "IContextDecorator")
0112 .def("decorate", &IContextDecorator::decorate)
0113 .def("name", &IContextDecorator::name);
0114
0115 py::enum_<ProcessCode>(mex, "ProcessCode")
0116 .value("SUCCESS", ProcessCode::SUCCESS)
0117 .value("ABORT", ProcessCode::ABORT)
0118 .value("END", ProcessCode::END);
0119
0120 py::class_<WhiteBoard>(mex, "WhiteBoard")
0121 .def(py::init([](Acts::Logging::Level level, const std::string& name) {
0122 return std::make_unique<WhiteBoard>(
0123 Acts::getDefaultLogger(name, level));
0124 }),
0125 py::arg("level"), py::arg("name") = "WhiteBoard")
0126 .def("exists", &WhiteBoard::exists)
0127 .def_property_readonly("keys", &WhiteBoard::getKeys);
0128
0129 py::class_<AlgorithmContext>(mex, "AlgorithmContext")
0130 .def(py::init<std::size_t, std::size_t, WhiteBoard&, std::size_t>(),
0131 "alg"_a, "event"_a, "store"_a, "thread"_a)
0132 .def_readonly("algorithmNumber", &AlgorithmContext::algorithmNumber)
0133 .def_readonly("eventNumber", &AlgorithmContext::eventNumber)
0134 .def_property_readonly("eventStore",
0135 [](const AlgorithmContext& self) -> WhiteBoard& {
0136 return self.eventStore;
0137 })
0138 .def_readonly("threadId", &AlgorithmContext::threadId)
0139 .def_readonly("magFieldContext", &AlgorithmContext::magFieldContext)
0140 .def_readonly("geoContext", &AlgorithmContext::geoContext)
0141 .def_readonly("calibContext", &AlgorithmContext::calibContext)
0142 .def_readwrite("fpeMonitor", &AlgorithmContext::fpeMonitor);
0143
0144 auto pySequenceElement =
0145 py::class_<ActsExamples::SequenceElement, PySequenceElement,
0146 std::shared_ptr<ActsExamples::SequenceElement>>(
0147 mex, "SequenceElement")
0148 .def("internalExecute", &SequenceElement::internalExecute)
0149 .def("name", &SequenceElement::name);
0150
0151 auto bareAlgorithm =
0152 py::class_<ActsExamples::IAlgorithm,
0153 std::shared_ptr<ActsExamples::IAlgorithm>, SequenceElement,
0154 PyIAlgorithm>(mex, "IAlgorithm")
0155 .def(py::init_alias<const std::string&, Acts::Logging::Level>(),
0156 py::arg("name"), py::arg("level"))
0157 .def("execute", &IAlgorithm::execute);
0158
0159 using ActsExamples::Sequencer;
0160 using Config = Sequencer::Config;
0161 auto sequencer =
0162 py::class_<Sequencer>(mex, "_Sequencer")
0163 .def(py::init([](Config cfg) {
0164 cfg.iterationCallback = []() {
0165 py::gil_scoped_acquire gil;
0166 if (PyErr_CheckSignals() != 0) {
0167 throw py::error_already_set{};
0168 }
0169 };
0170 return std::make_unique<Sequencer>(cfg);
0171 }))
0172 .def("run",
0173 [](Sequencer& self) {
0174 py::gil_scoped_release gil;
0175 int res = self.run();
0176 if (res != EXIT_SUCCESS) {
0177 throw std::runtime_error{"Sequencer terminated abnormally"};
0178 }
0179 })
0180 .def("addContextDecorator", &Sequencer::addContextDecorator)
0181 .def("addAlgorithm", &Sequencer::addAlgorithm, py::keep_alive<1, 2>())
0182 .def("addReader", &Sequencer::addReader)
0183 .def("addWriter", &Sequencer::addWriter)
0184 .def("addWhiteboardAlias", &Sequencer::addWhiteboardAlias)
0185 .def_property_readonly("config", &Sequencer::config)
0186 .def_property_readonly("fpeResult", &Sequencer::fpeResult)
0187 .def_property_readonly_static(
0188 "_sourceLocation",
0189 [](py::object ) { return std::string{__FILE__}; });
0190
0191 auto c = py::class_<Config>(sequencer, "Config").def(py::init<>());
0192
0193 ACTS_PYTHON_STRUCT(c, skip, events, logLevel, numThreads, outputDir,
0194 outputTimingFile, trackFpes, fpeMasks, failOnFirstFpe,
0195 fpeStackTraceLength);
0196
0197 auto fpem =
0198 py::class_<Sequencer::FpeMask>(sequencer, "_FpeMask")
0199 .def(py::init<>())
0200 .def(py::init<std::string, std::pair<unsigned int, unsigned int>,
0201 Acts::FpeType, std::size_t>())
0202 .def("__repr__", [](const Sequencer::FpeMask& self) {
0203 std::stringstream ss;
0204 ss << self;
0205 return ss.str();
0206 });
0207
0208 ACTS_PYTHON_STRUCT(fpem, file, lines, type, count);
0209
0210 struct FpeMonitorContext {
0211 std::optional<Acts::FpeMonitor> mon;
0212 };
0213
0214 auto fpe = py::class_<Acts::FpeMonitor>(m, "FpeMonitor")
0215 .def_static("_trigger_divbyzero", &trigger_divbyzero)
0216 .def_static("_trigger_overflow", &trigger_overflow)
0217 .def_static("_trigger_invalid", &trigger_invalid)
0218 .def_static("context", []() { return FpeMonitorContext(); });
0219
0220 fpe.def_property_readonly("result",
0221 py::overload_cast<>(&Acts::FpeMonitor::result),
0222 py::return_value_policy::reference_internal)
0223 .def("rearm", &Acts::FpeMonitor::rearm);
0224
0225 py::class_<Acts::FpeMonitor::Result>(fpe, "Result")
0226 .def("merged", &Acts::FpeMonitor::Result::merged)
0227 .def("merge", &Acts::FpeMonitor::Result::merge)
0228 .def("count", &Acts::FpeMonitor::Result::count)
0229 .def("__str__", [](const Acts::FpeMonitor::Result& result) {
0230 std::stringstream os;
0231 result.summary(os);
0232 return os.str();
0233 });
0234
0235 py::class_<FpeMonitorContext>(m, "_FpeMonitorContext")
0236 .def(py::init([]() { return std::make_unique<FpeMonitorContext>(); }))
0237 .def(
0238 "__enter__",
0239 [](FpeMonitorContext& fm) -> Acts::FpeMonitor& {
0240 fm.mon.emplace();
0241 return fm.mon.value();
0242 },
0243 py::return_value_policy::reference_internal)
0244 .def("__exit__", [](FpeMonitorContext& fm, py::object ,
0245 py::object ,
0246 py::object ) { fm.mon.reset(); });
0247
0248 py::enum_<Acts::FpeType>(m, "FpeType")
0249 .value("INTDIV", Acts::FpeType::INTDIV)
0250 .value("INTOVF", Acts::FpeType::INTOVF)
0251 .value("FLTDIV", Acts::FpeType::FLTDIV)
0252 .value("FLTOVF", Acts::FpeType::FLTOVF)
0253 .value("FLTUND", Acts::FpeType::FLTUND)
0254 .value("FLTRES", Acts::FpeType::FLTRES)
0255 .value("FLTINV", Acts::FpeType::FLTINV)
0256 .value("FLTSUB", Acts::FpeType::FLTSUB)
0257
0258 .def_property_readonly_static(
0259 "values", [](py::object ) -> const auto& {
0260 static const std::vector<Acts::FpeType> values = {
0261 Acts::FpeType::INTDIV, Acts::FpeType::INTOVF,
0262 Acts::FpeType::FLTDIV, Acts::FpeType::FLTOVF,
0263 Acts::FpeType::FLTUND, Acts::FpeType::FLTRES,
0264 Acts::FpeType::FLTINV, Acts::FpeType::FLTSUB};
0265 return values;
0266 });
0267
0268 py::register_exception<ActsExamples::FpeFailure>(m, "FpeFailure",
0269 PyExc_RuntimeError);
0270
0271 using ActsExamples::RandomNumbers;
0272 auto randomNumbers =
0273 py::class_<RandomNumbers, std::shared_ptr<RandomNumbers>>(mex,
0274 "RandomNumbers")
0275 .def(py::init<const RandomNumbers::Config&>());
0276
0277 py::class_<ActsExamples::RandomEngine>(mex, "RandomEngine").def(py::init<>());
0278
0279 py::class_<RandomNumbers::Config>(randomNumbers, "Config")
0280 .def(py::init<>())
0281 .def_readwrite("seed", &RandomNumbers::Config::seed);
0282
0283
0284 }
0285
0286 }