Line data Source code
1 : /**
2 : * @file trigger_primitive.cpp Python bindings for the trigger primitive formats
3 : *
4 : * This is part of the DUNE DAQ Software Suite, copyright 2020.
5 : * Licensing/copyright details are in the COPYING file that you should have
6 : * received with this code.
7 : */
8 :
9 : #include "trgdataformats/TriggerObjectOverlay.hpp"
10 :
11 : #include <pybind11/pybind11.h>
12 : #include <pybind11/stl.h>
13 : #include <cstring>
14 :
15 : namespace py = pybind11;
16 :
17 : // NOLINTBEGIN(build/unsigned)
18 :
19 : namespace dunedaq {
20 : namespace trgdataformats {
21 : namespace python {
22 :
23 : /*
24 : Doesn't work
25 : */
26 : struct TriggerCandidateHolder {
27 :
28 :
29 0 : TriggerCandidateHolder(void* ptr, size_t size) {
30 0 : m_size = size;
31 0 : m_data.reset(new uint8_t[m_size]);
32 0 : std::memcpy(m_data.get(), ptr, size);
33 0 : }
34 :
35 0 : TriggerCandidate* ptr() { return reinterpret_cast<TriggerCandidate*>(m_data.get()); }
36 :
37 : size_t m_size;
38 : std::unique_ptr<uint8_t[]> m_data;
39 :
40 : };
41 :
42 : void
43 0 : register_trigger_candidate(py::module& m)
44 : {
45 :
46 0 : m.def("string_to_trigger_candidate_type", &trgdataformats::string_to_trigger_candidate_type);
47 0 : m.def("trigger_candidate_type_to_string", &trgdataformats::trigger_candidate_type_to_string);
48 :
49 0 : py::class_<TriggerCandidateData> trigger_candidate_data(m, "TriggerCandidateData", py::buffer_protocol());
50 0 : trigger_candidate_data
51 0 : .def(py::init())
52 0 : .def(py::init([](py::capsule capsule) {
53 0 : auto tp = *static_cast<TriggerCandidateData*>(capsule.get_pointer());
54 0 : return tp;
55 : } ))
56 0 : .def(py::init([](py::bytes bytes){
57 0 : py::buffer_info info(py::buffer(bytes).request());
58 0 : auto tp = *static_cast<TriggerCandidateData*>(info.ptr);
59 0 : return tp;
60 0 : }))
61 0 : .def_property_readonly_static("s_trigger_candidate_version", [](py::object /*self*/) { return TriggerCandidateData::s_trigger_candidate_version; })
62 0 : .def_property_readonly("version", [](TriggerCandidateData& self) -> uint16_t {return self.version;})
63 0 : .def_property_readonly("time_start", [](TriggerCandidateData& self) -> uint64_t {return self.time_start;})
64 0 : .def_property_readonly("time_end", [](TriggerCandidateData& self) -> uint64_t {return self.time_end;})
65 0 : .def_property_readonly("time_candidate", [](TriggerCandidateData& self) -> uint64_t {return self.time_candidate;})
66 0 : .def_property_readonly("detid", [](TriggerCandidateData& self) -> uint16_t {return self.detid;})
67 0 : .def_property_readonly("type", [](TriggerCandidateData& self) -> TriggerCandidateData::Type {return self.type;})
68 0 : .def_property_readonly("algorithm", [](TriggerCandidateData& self) -> TriggerCandidateData::Algorithm {return self.algorithm;})
69 0 : .def_static("sizeof", [](){ return sizeof(TriggerCandidateData); })
70 : ;
71 :
72 0 : py::enum_<TriggerCandidateData::Type>(trigger_candidate_data, "Type")
73 0 : .value("kUnknown", TriggerCandidateData::Type::kUnknown)
74 0 : .value("kTiming", TriggerCandidateData::Type::kTiming)
75 0 : .value("kTPCLowE", TriggerCandidateData::Type::kTPCLowE)
76 0 : .value("kSupernova", TriggerCandidateData::Type::kSupernova)
77 0 : .value("kRandom", TriggerCandidateData::Type::kRandom)
78 0 : .value("kPrescale", TriggerCandidateData::Type::kPrescale)
79 0 : .value("kADCSimpleWindow", TriggerCandidateData::Type::kADCSimpleWindow)
80 0 : .value("kHorizontalMuon", TriggerCandidateData::Type::kHorizontalMuon)
81 0 : .value("kMichelElectron", TriggerCandidateData::Type::kMichelElectron)
82 0 : .value("kPlaneCoincidence", TriggerCandidateData::Type::kPlaneCoincidence)
83 0 : .value("kBundle", TriggerCandidateData::Type::kBundle)
84 0 : .value("kChannelDistance", TriggerCandidateData::Type::kChannelDistance)
85 0 : .value("kDBSCAN", TriggerCandidateData::Type::kDBSCAN)
86 0 : .value("kCTBFakeTrigger", TriggerCandidateData::Type::kCTBFakeTrigger)
87 0 : .value("kCTBBeam", TriggerCandidateData::Type::kCTBBeam)
88 0 : .value("kCTBBeamChkvHL", TriggerCandidateData::Type::kCTBBeamChkvHL)
89 0 : .value("kCTBCustomD", TriggerCandidateData::Type::kCTBCustomD)
90 0 : .value("kCTBCustomE", TriggerCandidateData::Type::kCTBCustomE)
91 0 : .value("kCTBCustomF", TriggerCandidateData::Type::kCTBCustomF)
92 0 : .value("kCTBCustomG", TriggerCandidateData::Type::kCTBCustomG)
93 0 : .value("kCTBBeamChkvHLx", TriggerCandidateData::Type::kCTBBeamChkvHLx)
94 0 : .value("kCTBBeamChkvHxL", TriggerCandidateData::Type::kCTBBeamChkvHxL)
95 0 : .value("kCTBBeamChkvHxLx", TriggerCandidateData::Type::kCTBBeamChkvHxLx)
96 0 : .value("kNeutronSourceCalib", TriggerCandidateData::Type::kNeutronSourceCalib)
97 0 : .value("kChannelAdjacency", TriggerCandidateData::Type::kChannelAdjacency)
98 0 : .value("kCIBFakeTrigger", TriggerCandidateData::Type::kCIBFakeTrigger)
99 0 : .value("kCIBLaserTriggerP1", TriggerCandidateData::Type::kCIBLaserTriggerP1)
100 0 : .value("kCIBLaserTriggerP2", TriggerCandidateData::Type::kCIBLaserTriggerP2)
101 0 : .value("kCIBLaserTriggerP3", TriggerCandidateData::Type::kCIBLaserTriggerP3)
102 0 : .value("kCTBOffSpillSnapshot", TriggerCandidateData::Type::kCTBOffSpillSnapshot)
103 0 : .value("kCTBOffSpillCosmicJura", TriggerCandidateData::Type::kCTBOffSpillCosmicJura)
104 0 : .value("kCTBOffSpillCRTCosmic", TriggerCandidateData::Type::kCTBOffSpillCRTCosmic)
105 0 : .value("kCTBBeamSpillStart", TriggerCandidateData::Type::kCTBBeamSpillStart)
106 0 : .value("kCTBBeamSpillSnapshot", TriggerCandidateData::Type::kCTBBeamSpillSnapshot)
107 0 : .value("kCTBCustomC", TriggerCandidateData::Type::kCTBCustomC)
108 0 : .value("kCTBCustomPulseTrain", TriggerCandidateData::Type::kCTBCustomPulseTrain)
109 0 : .value("kDTSPulser", TriggerCandidateData::Type::kDTSPulser)
110 0 : .value("kDTSCosmic", TriggerCandidateData::Type::kDTSCosmic)
111 0 : .value("kSSPLEDCalibration", TriggerCandidateData::Type::kSSPLEDCalibration)
112 0 : .value("kProtoDUNEBSMWindow", TriggerCandidateData::Type::kProtoDUNEBSMWindow);
113 :
114 0 : py::enum_<TriggerCandidateData::Algorithm>(trigger_candidate_data, "Algorithm")
115 0 : .value("kUnknown", TriggerCandidateData::Algorithm::kUnknown)
116 0 : .value("kSupernova", TriggerCandidateData::Algorithm::kSupernova)
117 0 : .value("kHSIEventToTriggerCandidate", TriggerCandidateData::Algorithm::kHSIEventToTriggerCandidate)
118 0 : .value("kPrescale", TriggerCandidateData::Algorithm::kPrescale)
119 0 : .value("kADCSimpleWindow", TriggerCandidateData::Algorithm::kADCSimpleWindow)
120 0 : .value("kHorizontalMuon", TriggerCandidateData::Algorithm::kHorizontalMuon)
121 0 : .value("kMichelElectron", TriggerCandidateData::Algorithm::kMichelElectron)
122 0 : .value("kPlaneCoincidence", TriggerCandidateData::Algorithm::kPlaneCoincidence)
123 0 : .value("kCustom", TriggerCandidateData::Algorithm::kCustom)
124 0 : .value("kDBSCAN", TriggerCandidateData::Algorithm::kDBSCAN)
125 0 : .value("kChannelDistance", TriggerCandidateData::Algorithm::kChannelDistance)
126 0 : .value("kBundle", TriggerCandidateData::Algorithm::kBundle)
127 0 : .value("kChannelAdjacency", TriggerCandidateData::Algorithm::kChannelAdjacency);
128 :
129 0 : py::class_<TriggerCandidate>(m, "TriggerCandidateOverlay", py::buffer_protocol())
130 0 : .def(py::init([](py::capsule capsule) {
131 0 : auto tp = *static_cast<TriggerCandidate*>(capsule.get_pointer());
132 0 : return tp;
133 : } ))
134 0 : .def_property_readonly("data", [](TriggerCandidate& self) -> TriggerCandidateData& {return self.data;})
135 0 : .def("__len__", [](TriggerCandidate& self){ return self.n_inputs; })
136 0 : .def("sizeof", [](TriggerCandidate& self){ return sizeof(TriggerCandidate)+self.n_inputs*sizeof(TriggerActivityData); })
137 : ;
138 :
139 :
140 0 : py::class_<TriggerCandidateHolder>(m, "TriggerCandidate", py::buffer_protocol())
141 0 : .def(py::init([](py::capsule capsule) {
142 0 : auto tc_ptr = static_cast<TriggerCandidate*>(capsule.get_pointer());
143 0 : TriggerCandidateHolder tch(tc_ptr, sizeof(TriggerCandidate)+tc_ptr->n_inputs*sizeof(TriggerActivityData));
144 0 : return tch;
145 : }))
146 0 : .def(py::init([](py::bytes bytes){
147 0 : py::buffer_info info(py::buffer(bytes).request());
148 :
149 0 : TriggerCandidateHolder tch(info.ptr, info.size);
150 :
151 0 : return tch;
152 0 : }))
153 :
154 0 : .def("get_bytes",
155 0 : [](TriggerCandidateHolder& tch) -> py::bytes {
156 0 : return py::bytes(reinterpret_cast<char*>(tch.ptr()), tch.m_size);
157 0 : }, py::return_value_policy::reference_internal
158 : )
159 0 : .def_property_readonly("data", [](TriggerCandidateHolder& self) -> TriggerCandidateData& {return self.ptr()->data;})
160 0 : .def("n_inputs", [](TriggerCandidateHolder& self){ return self.ptr()->n_inputs; })
161 0 : .def("__len__", [](TriggerCandidateHolder& self){ return self.ptr()->n_inputs; })
162 0 : .def("__getitem__",
163 0 : [](TriggerCandidateHolder &self, size_t i) -> const TriggerActivityData& {
164 0 : if (i >= self.ptr()->n_inputs) {
165 0 : throw py::index_error();
166 : }
167 0 : return self.ptr()->inputs[i];
168 0 : }, py::return_value_policy::reference_internal)
169 0 : .def("sizeof", [](TriggerCandidateHolder& self){ return self.m_size; })
170 : ;
171 0 : } // NOLINT function length, while long enough to trip the linter, is fine
172 :
173 : } // namespace python
174 : } // namespace trgdataformats
175 : } // namespace dunedaq
176 :
177 : static_assert(
178 : dunedaq::trgdataformats::TriggerCandidateData::s_trigger_candidate_version == 3,
179 : "Version of TriggerCandidateData appears to have changed; as a developer please update the Python bindings in this file before updating this static_assert");
180 :
181 : // NOLINTEND(build/unsigned)
|