Line data Source code
1 : /**
2 : * @file DAPHNEEthUnpacker.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/DAPHNEEthFrame.hpp"
11 : #include "fddetdataformats/DAPHNEEthStreamFrame.hpp"
12 :
13 : #include <cstdint>
14 : #include <pybind11/numpy.h>
15 :
16 : namespace py = pybind11;
17 : namespace dunedaq::rawdatautils::daphneeth {
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::DAPHNEEthFrame);
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::DAPHNEEthStreamFrame);
35 : }
36 :
37 : /**
38 : * @brief Unpacks channel numbers for DAPHNEEthStreamFrames 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::DAPHNEEthStreamFrame::s_num_channels;
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::DAPHNEEthStreamFrame*>(
52 0 : static_cast<char*>(data) + i * sizeof(fddetdataformats::DAPHNEEthStreamFrame));
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::DAPHNEEthFrame*>(static_cast<char*>(data) +
77 0 : i * sizeof(fddetdataformats::DAPHNEEthFrame));
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::DAPHNEEthFrame));
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::DAPHNEEthStreamFrame));
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::DAPHNEEthFrame::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::DAPHNEEthFrame*>(static_cast<char*>(data) +
120 0 : i * sizeof(fddetdataformats::DAPHNEEthFrame));
121 0 : for (size_t j = 0; j < adcs_per_channel; ++j) {
122 0 : ptr[i * adcs_per_channel + j] = fr->get_adc(j);
123 : }
124 : // for (size_t j=0; j<channels_per_daphne; ++j)
125 : }
126 0 : ret.resize({ nframes, adcs_per_channel });
127 :
128 0 : return ret;
129 0 : }
130 :
131 : /**
132 : * @brief Unpacks data containing DAPHNEStreamFrames into a numpy array with the ADC
133 : * values and dimension (number of DAPHNEStreamFrames * adcs_per_channel (64), channels_per_frame (4))
134 : * Warning: It doesn't check that nframes is a sensible value (can read out of bounds)
135 : */
136 : py::array_t<uint16_t>
137 0 : np_array_adc_stream_data(void* data, int nframes)
138 : {
139 :
140 0 : const auto channels_per_daphne = fddetdataformats::DAPHNEEthStreamFrame::s_num_channels;
141 0 : const auto adcs_per_channel = fddetdataformats::DAPHNEEthStreamFrame::s_adcs_per_channel;
142 :
143 0 : py::array_t<uint16_t> ret(channels_per_daphne * nframes * adcs_per_channel);
144 0 : auto ptr = static_cast<uint16_t*>(ret.request().ptr);
145 0 : for (size_t i = 0; i < (size_t)nframes; ++i) {
146 0 : auto fr = reinterpret_cast<fddetdataformats::DAPHNEEthStreamFrame*>(
147 0 : static_cast<char*>(data) + i * sizeof(fddetdataformats::DAPHNEEthStreamFrame));
148 0 : for (size_t j = 0; j < adcs_per_channel; ++j)
149 0 : for (size_t k = 0; k < channels_per_daphne; ++k)
150 0 : ptr[channels_per_daphne * (adcs_per_channel * i + j) + k] = fr->get_adc(j, k);
151 : }
152 0 : ret.resize({ nframes * adcs_per_channel, channels_per_daphne });
153 :
154 0 : return ret;
155 0 : }
156 :
157 : /**
158 : * @brief Unpacks data containing DAPHNEFrames into a numpy array with the
159 : * timestamps with dimension (number of DAPHNEFrames)
160 : * Warning: It doesn't check that nframes is a sensible value (can read out of bounds)
161 : */
162 :
163 : py::array_t<uint64_t>
164 0 : np_array_timestamp_data(void* data, int nframes)
165 : {
166 :
167 0 : py::array_t<uint64_t> ret(nframes);
168 0 : auto ptr = static_cast<uint64_t*>(ret.request().ptr);
169 0 : for (size_t i = 0; i < (size_t)nframes; ++i) {
170 0 : auto fr = reinterpret_cast<fddetdataformats::DAPHNEEthFrame*>(static_cast<char*>(data) +
171 0 : i * sizeof(fddetdataformats::DAPHNEEthFrame));
172 0 : ptr[i] = fr->get_timestamp();
173 : }
174 :
175 0 : return ret;
176 0 : }
177 :
178 : /**
179 : * @brief Unpacks data containing DAPHNEStreamFrames into a numpy array with the
180 : * timestamps with dimension (number of DAPHNEStreamFrames)
181 : * Warning: It doesn't check that nframes is a sensible value (can read out of bounds)
182 : */
183 : py::array_t<uint64_t>
184 0 : np_array_timestamp_stream_data(void* data, int nframes)
185 : {
186 :
187 0 : const auto adcs_per_channel = fddetdataformats::DAPHNEEthStreamFrame::s_adcs_per_channel;
188 0 : const size_t ticks_per_adc = 1;
189 :
190 0 : py::array_t<uint64_t> ret(nframes * adcs_per_channel);
191 :
192 0 : auto ptr = static_cast<uint64_t*>(ret.request().ptr);
193 0 : for (size_t i = 0; i < (size_t)nframes; ++i) {
194 0 : auto fr = reinterpret_cast<fddetdataformats::DAPHNEEthStreamFrame*>(
195 0 : static_cast<char*>(data) + i * sizeof(fddetdataformats::DAPHNEEthStreamFrame));
196 0 : for (size_t j = 0; j < adcs_per_channel; ++j)
197 0 : ptr[i * adcs_per_channel + j] = fr->get_timestamp() + j * ticks_per_adc;
198 : }
199 :
200 0 : return ret;
201 0 : }
202 :
203 : /**
204 : * @brief Unpacks a Fragment containing DAPHNEFrames into a numpy array with the
205 : * ADC values and dimension (number of DAPHNEFrames in the Fragment, 320)
206 : */
207 : py::array_t<uint16_t>
208 0 : np_array_adc(daqdataformats::Fragment& frag)
209 : {
210 0 : return np_array_adc_data(frag.get_data(),
211 0 : (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) /
212 0 : sizeof(fddetdataformats::DAPHNEEthFrame));
213 : }
214 :
215 : /**
216 : * @brief Unpacks a Fragment containing DAPHNEStreamFrames into a numpy array with the
217 : * ADC values and dimension (number of DAPHNEStreamFrames in the Fragment, 4)
218 : */
219 : py::array_t<uint16_t>
220 0 : np_array_adc_stream(daqdataformats::Fragment& frag)
221 : {
222 0 : return np_array_adc_stream_data(frag.get_data(),
223 0 : (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) /
224 0 : sizeof(fddetdataformats::DAPHNEEthStreamFrame));
225 : }
226 :
227 : /**
228 : * @brief Unpacks the timestamps in a Fragment containing WIBFrames into a numpy
229 : * array with dimension (number of DAPHNEFrames in the Fragment)
230 : */
231 : py::array_t<uint64_t>
232 0 : np_array_timestamp(daqdataformats::Fragment& frag)
233 : {
234 0 : return np_array_timestamp_data(frag.get_data(),
235 0 : (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) /
236 0 : sizeof(fddetdataformats::DAPHNEEthFrame));
237 : }
238 :
239 : /**
240 : * @brief Unpacks the timestamps in a Fragment containing DAPHNEStreamFrames into a numpy
241 : * array with dimension (number of DAPHNEStreamFrames in the Fragment)
242 : */
243 : py::array_t<uint64_t>
244 0 : np_array_timestamp_stream(daqdataformats::Fragment& frag)
245 : {
246 0 : return np_array_timestamp_stream_data(frag.get_data(),
247 0 : (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) /
248 0 : sizeof(fddetdataformats::DAPHNEEthStreamFrame));
249 : }
250 :
251 : } // namespace dunedaq::rawdatautils::daphne // NOLINT
|