Line data Source code
1 : /**
2 : * @file DAPHNEUnpacker.cc Fast C++ -> numpy DAPHNE format unpacker
3 : *
4 : * This is part of the DUNE DAQ , copyright 2020.
5 : * Licensing/copyright details are in the COPYING file that you should have
6 : * received with this code.
7 : */
8 :
9 : #include "daqdataformats/Fragment.hpp"
10 : #include "fddetdataformats/DAPHNEFrame.hpp"
11 : #include "fddetdataformats/DAPHNEStreamFrame.hpp"
12 :
13 : #include <cstdint>
14 : #include <pybind11/numpy.h>
15 :
16 : namespace py = pybind11;
17 : namespace dunedaq::rawdatautils::daphne {
18 :
19 : /**
20 : * @brief Gets number of DAPHNEFrames in a fragment
21 : */
22 : uint32_t
23 0 : get_n_frames(daqdataformats::Fragment const& frag)
24 : {
25 0 : return (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) / sizeof(fddetdataformats::DAPHNEFrame);
26 : }
27 :
28 : /**
29 : * @brief Gets number of DAPHNEStreamFrames in a fragment
30 : */
31 : uint32_t
32 0 : get_n_frames_stream(daqdataformats::Fragment const& frag)
33 : {
34 0 : return (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) / sizeof(fddetdataformats::DAPHNEStreamFrame);
35 : }
36 :
37 : /**
38 : * @brief Unpacks channel numbers for DAPHNEStreamFrames into a numpy array with dimensions
39 : * (nframes, s_channels_per_frame)
40 : */
41 :
42 : py::array_t<uint8_t>
43 0 : np_array_channels_stream_data(void* data, int nframes)
44 : {
45 :
46 0 : const auto channels_per_daphne = fddetdataformats::DAPHNEStreamFrame::s_channels_per_frame;
47 0 : py::array_t<uint8_t> channels(channels_per_daphne * nframes);
48 0 : auto ptr = static_cast<uint8_t*>(channels.request().ptr);
49 :
50 0 : for (size_t i = 0; i < (size_t)nframes; ++i) {
51 0 : auto fr = reinterpret_cast<fddetdataformats::DAPHNEStreamFrame*>(static_cast<char*>(data) +
52 0 : i * sizeof(fddetdataformats::DAPHNEStreamFrame));
53 :
54 0 : ptr[i * channels_per_daphne + 0] = fr->get_channel0();
55 0 : ptr[i * channels_per_daphne + 1] = fr->get_channel1();
56 0 : ptr[i * channels_per_daphne + 2] = fr->get_channel2();
57 0 : ptr[i * channels_per_daphne + 3] = fr->get_channel3();
58 : }
59 0 : channels.resize({ nframes, channels_per_daphne });
60 :
61 0 : return channels;
62 0 : }
63 :
64 : /**
65 : * @brief Unpacks channel numbers for DAPHNEFrames into a numpy array with dimensions
66 : * (nframes)
67 : */
68 : py::array_t<uint8_t>
69 0 : np_array_channels_data(void* data, int nframes)
70 : {
71 :
72 0 : py::array_t<uint8_t> channels(nframes);
73 0 : auto ptr = static_cast<uint8_t*>(channels.request().ptr);
74 :
75 0 : for (size_t i = 0; i < (size_t)nframes; ++i) {
76 0 : auto fr = reinterpret_cast<fddetdataformats::DAPHNEFrame*>(static_cast<char*>(data) +
77 0 : i * sizeof(fddetdataformats::DAPHNEFrame));
78 0 : ptr[i] = fr->get_channel();
79 : }
80 :
81 0 : return channels;
82 0 : }
83 :
84 : /**
85 : * @brief Unpacks channel numbers for Fragment that contains DAPHNEFrames into a numpy array with dimensions */
86 : py::array_t<uint8_t>
87 0 : np_array_channels(daqdataformats::Fragment& frag)
88 : {
89 0 : return np_array_channels_data(frag.get_data(),
90 0 : (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) /
91 0 : sizeof(fddetdataformats::DAPHNEFrame));
92 : }
93 :
94 : /**
95 : * @brief Unpacks channel numbers for Fragment that contains DAPHNEStreamFrames into a numpy array with dimensions
96 : */
97 : py::array_t<uint8_t>
98 0 : np_array_channels_stream(daqdataformats::Fragment& frag)
99 : {
100 0 : return np_array_channels_stream_data(frag.get_data(),
101 0 : (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) /
102 0 : sizeof(fddetdataformats::DAPHNEStreamFrame));
103 : }
104 :
105 : /**
106 : * @brief Unpacks data containing DAPHNEFrames into a numpy array with the ADC
107 : * values and dimension (number of DAPHNEFrames, channels_per_daphne)
108 : * Warning: It doesn't check that nframes is a sensible value (can read out of bounds)
109 : */
110 : py::array_t<uint16_t>
111 0 : np_array_adc_data(void* data, int nframes)
112 : {
113 :
114 0 : const auto adcs_per_channel = fddetdataformats::DAPHNEFrame::s_num_adcs;
115 :
116 0 : py::array_t<uint16_t> ret(nframes * adcs_per_channel);
117 0 : auto ptr = static_cast<uint16_t*>(ret.request().ptr);
118 0 : for (size_t i = 0; i < (size_t)nframes; ++i) {
119 0 : auto fr = reinterpret_cast<fddetdataformats::DAPHNEFrame*>(static_cast<char*>(data) +
120 0 : i * sizeof(fddetdataformats::DAPHNEFrame));
121 : // auto fr = reinterpret_cast<fddetdataformats::DAPHNEFrame*>(static_cast<char*>(data) + i *
122 : // sizeof(fddetdataformats::DAPHNEFrame));
123 0 : for (size_t j = 0; j < adcs_per_channel; ++j) {
124 0 : ptr[i * adcs_per_channel + j] = fr->get_adc(j);
125 : }
126 : // for (size_t j=0; j<channels_per_daphne; ++j)
127 : }
128 0 : ret.resize({ nframes, adcs_per_channel });
129 :
130 0 : return ret;
131 0 : }
132 :
133 : /**
134 : * @brief Unpacks data containing DAPHNEStreamFrames into a numpy array with the ADC
135 : * values and dimension (number of DAPHNEStreamFrames * adcs_per_channel (64), channels_per_frame (4))
136 : * Warning: It doesn't check that nframes is a sensible value (can read out of bounds)
137 : */
138 : py::array_t<uint16_t>
139 0 : np_array_adc_stream_data(void* data, int nframes)
140 : {
141 :
142 0 : const auto channels_per_daphne = fddetdataformats::DAPHNEStreamFrame::s_channels_per_frame;
143 0 : const auto adcs_per_channel = fddetdataformats::DAPHNEStreamFrame::s_adcs_per_channel;
144 :
145 0 : py::array_t<uint16_t> ret(channels_per_daphne * nframes * adcs_per_channel);
146 0 : auto ptr = static_cast<uint16_t*>(ret.request().ptr);
147 0 : for (size_t i = 0; i < (size_t)nframes; ++i) {
148 0 : auto fr = reinterpret_cast<fddetdataformats::DAPHNEStreamFrame*>(static_cast<char*>(data) +
149 0 : i * sizeof(fddetdataformats::DAPHNEStreamFrame));
150 0 : for (size_t j = 0; j < adcs_per_channel; ++j)
151 0 : for (size_t k = 0; k < channels_per_daphne; ++k)
152 0 : ptr[channels_per_daphne * (adcs_per_channel * i + j) + k] = fr->get_adc(j, k);
153 : }
154 0 : ret.resize({ nframes * adcs_per_channel, channels_per_daphne });
155 :
156 0 : return ret;
157 0 : }
158 :
159 : /**
160 : * @brief Unpacks data containing DAPHNEFrames into a numpy array with the
161 : * timestamps with dimension (number of DAPHNEFrames)
162 : * Warning: It doesn't check that nframes is a sensible value (can read out of bounds)
163 : */
164 :
165 : py::array_t<uint64_t>
166 0 : np_array_timestamp_data(void* data, int nframes)
167 : {
168 :
169 0 : py::array_t<uint64_t> ret(nframes);
170 0 : auto ptr = static_cast<uint64_t*>(ret.request().ptr);
171 0 : for (size_t i = 0; i < (size_t)nframes; ++i) {
172 0 : auto fr = reinterpret_cast<fddetdataformats::DAPHNEFrame*>(static_cast<char*>(data) +
173 0 : i * sizeof(fddetdataformats::DAPHNEFrame));
174 0 : ptr[i] = fr->get_timestamp();
175 : }
176 :
177 0 : return ret;
178 0 : }
179 :
180 : /**
181 : * @brief Unpacks data containing DAPHNEStreamFrames into a numpy array with the
182 : * timestamps with dimension (number of DAPHNEStreamFrames)
183 : * Warning: It doesn't check that nframes is a sensible value (can read out of bounds)
184 : */
185 : py::array_t<uint64_t>
186 0 : np_array_timestamp_stream_data(void* data, int nframes)
187 : {
188 :
189 0 : const auto adcs_per_channel = fddetdataformats::DAPHNEStreamFrame::s_adcs_per_channel;
190 0 : const size_t ticks_per_adc = 1;
191 :
192 0 : py::array_t<uint64_t> ret(nframes * adcs_per_channel);
193 :
194 0 : auto ptr = static_cast<uint64_t*>(ret.request().ptr);
195 0 : for (size_t i = 0; i < (size_t)nframes; ++i) {
196 0 : auto fr = reinterpret_cast<fddetdataformats::DAPHNEStreamFrame*>(static_cast<char*>(data) +
197 0 : i * sizeof(fddetdataformats::DAPHNEStreamFrame));
198 0 : for (size_t j = 0; j < adcs_per_channel; ++j)
199 0 : ptr[i * adcs_per_channel + j] = fr->get_timestamp() + j * ticks_per_adc;
200 : }
201 :
202 0 : return ret;
203 0 : }
204 :
205 : /**
206 : * @brief Unpacks a Fragment containing DAPHNEFrames into a numpy array with the
207 : * ADC values and dimension (number of DAPHNEFrames in the Fragment, 320)
208 : */
209 : py::array_t<uint16_t>
210 0 : np_array_adc(daqdataformats::Fragment& frag)
211 : {
212 0 : return np_array_adc_data(frag.get_data(),
213 0 : (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) /
214 0 : sizeof(fddetdataformats::DAPHNEFrame));
215 : }
216 :
217 : /**
218 : * @brief Unpacks a Fragment containing DAPHNEStreamFrames into a numpy array with the
219 : * ADC values and dimension (number of DAPHNEStreamFrames in the Fragment, 4)
220 : */
221 : py::array_t<uint16_t>
222 0 : np_array_adc_stream(daqdataformats::Fragment& frag)
223 : {
224 0 : return np_array_adc_stream_data(frag.get_data(),
225 0 : (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) /
226 0 : sizeof(fddetdataformats::DAPHNEStreamFrame));
227 : }
228 :
229 : /**
230 : * @brief Unpacks the timestamps in a Fragment containing WIBFrames into a numpy
231 : * array with dimension (number of DAPHNEFrames in the Fragment)
232 : */
233 : py::array_t<uint64_t>
234 0 : np_array_timestamp(daqdataformats::Fragment& frag)
235 : {
236 0 : return np_array_timestamp_data(frag.get_data(),
237 0 : (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) /
238 0 : sizeof(fddetdataformats::DAPHNEFrame));
239 : }
240 :
241 : /**
242 : * @brief Unpacks the timestamps in a Fragment containing DAPHNEStreamFrames into a numpy
243 : * array with dimension (number of DAPHNEStreamFrames in the Fragment)
244 : */
245 : py::array_t<uint64_t>
246 0 : np_array_timestamp_stream(daqdataformats::Fragment& frag)
247 : {
248 0 : return np_array_timestamp_stream_data(frag.get_data(),
249 0 : (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) /
250 0 : sizeof(fddetdataformats::DAPHNEStreamFrame));
251 : }
252 :
253 : } // namespace dunedaq::rawdatautils::daphne // NOLINT
|