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 "fddetdataformats/DAPHNEEthFrame.hpp"
10 : #include "fddetdataformats/DAPHNEEthStreamFrame.hpp"
11 : #include "daqdataformats/Fragment.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 0 : uint32_t get_n_frames(daqdataformats::Fragment const& frag){
23 0 : return (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) / sizeof(fddetdataformats::DAPHNEEthFrame);
24 : }
25 :
26 : /**
27 : * @brief Gets number of DAPHNEStreamFrames in a fragment
28 : */
29 0 : uint32_t get_n_frames_stream(daqdataformats::Fragment const& frag){
30 0 : return (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) / sizeof(fddetdataformats::DAPHNEEthStreamFrame);
31 : }
32 :
33 :
34 : /**
35 : * @brief Unpacks channel numbers for DAPHNEEthStreamFrames into a numpy array with dimensions
36 : * (nframes, s_channels_per_frame)
37 : */
38 :
39 0 : py::array_t<uint8_t> np_array_channels_stream_data(void* data, int nframes){
40 :
41 0 : const auto channels_per_daphne = fddetdataformats::DAPHNEEthStreamFrame::s_num_channels;
42 0 : py::array_t<uint8_t> channels(channels_per_daphne * nframes);
43 0 : auto ptr = static_cast<uint8_t*>(channels.request().ptr);
44 :
45 0 : for (size_t i=0; i<(size_t)nframes; ++i) {
46 0 : auto fr = reinterpret_cast<fddetdataformats::DAPHNEEthStreamFrame*>(static_cast<char*>(data) + i * sizeof(fddetdataformats::DAPHNEEthStreamFrame));
47 :
48 0 : ptr[i*channels_per_daphne + 0] = fr->get_channel0();
49 0 : ptr[i*channels_per_daphne + 1] = fr->get_channel1();
50 0 : ptr[i*channels_per_daphne + 2] = fr->get_channel2();
51 0 : ptr[i*channels_per_daphne + 3] = fr->get_channel3();
52 :
53 : }
54 0 : channels.resize({nframes, channels_per_daphne});
55 :
56 0 : return channels;
57 0 : }
58 :
59 : /**
60 : * @brief Unpacks channel numbers for DAPHNEFrames into a numpy array with dimensions
61 : * (nframes)
62 : */
63 0 : py::array_t<uint8_t> np_array_channels_data(void* data, int nframes){
64 :
65 0 : py::array_t<uint8_t> channels(nframes);
66 0 : auto ptr = static_cast<uint8_t*>(channels.request().ptr);
67 :
68 0 : for (size_t i=0; i<(size_t)nframes; ++i) {
69 0 : auto fr = reinterpret_cast<fddetdataformats::DAPHNEEthFrame*>(static_cast<char*>(data) + i * sizeof(fddetdataformats::DAPHNEEthFrame));
70 0 : ptr[i] = fr->get_channel();
71 : }
72 :
73 0 : return channels;
74 0 : }
75 :
76 : /**
77 : * @brief Unpacks channel numbers for Fragment that contains DAPHNEFrames into a numpy array with dimensions */
78 0 : py::array_t<uint8_t> np_array_channels(daqdataformats::Fragment& frag){
79 0 : return np_array_channels_data(frag.get_data(), (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) / sizeof(fddetdataformats::DAPHNEEthFrame));
80 : }
81 :
82 : /**
83 : * @brief Unpacks channel numbers for Fragment that contains DAPHNEStreamFrames into a numpy array with dimensions
84 : */
85 0 : py::array_t<uint8_t> np_array_channels_stream(daqdataformats::Fragment& frag){
86 0 : return np_array_channels_stream_data(frag.get_data(), (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) / sizeof(fddetdataformats::DAPHNEEthStreamFrame));
87 : }
88 :
89 :
90 : /**
91 : * @brief Unpacks data containing DAPHNEFrames into a numpy array with the ADC
92 : * values and dimension (number of DAPHNEFrames, channels_per_daphne)
93 : * Warning: It doesn't check that nframes is a sensible value (can read out of bounds)
94 : */
95 0 : py::array_t<uint16_t> np_array_adc_data(void* data, int nframes){
96 :
97 0 : const auto adcs_per_channel = fddetdataformats::DAPHNEEthFrame::s_num_adcs;
98 :
99 0 : py::array_t<uint16_t> ret(nframes * adcs_per_channel);
100 0 : auto ptr = static_cast<uint16_t*>(ret.request().ptr);
101 0 : for (size_t i=0; i<(size_t)nframes; ++i) {
102 0 : auto fr = reinterpret_cast<fddetdataformats::DAPHNEEthFrame*>(static_cast<char*>(data) + i * sizeof(fddetdataformats::DAPHNEEthFrame));
103 0 : for (size_t j=0; j<adcs_per_channel; ++j) {
104 0 : ptr[i*adcs_per_channel + j] = fr->get_adc(j);
105 : }
106 : //for (size_t j=0; j<channels_per_daphne; ++j)
107 :
108 : }
109 0 : ret.resize({nframes, adcs_per_channel});
110 :
111 0 : return ret;
112 0 : }
113 :
114 : /**
115 : * @brief Unpacks data containing DAPHNEStreamFrames into a numpy array with the ADC
116 : * values and dimension (number of DAPHNEStreamFrames * adcs_per_channel (64), channels_per_frame (4))
117 : * Warning: It doesn't check that nframes is a sensible value (can read out of bounds)
118 : */
119 0 : py::array_t<uint16_t> np_array_adc_stream_data(void* data, int nframes){
120 :
121 0 : const auto channels_per_daphne = fddetdataformats::DAPHNEEthStreamFrame::s_num_channels;
122 0 : const auto adcs_per_channel = fddetdataformats::DAPHNEEthStreamFrame::s_adcs_per_channel;
123 :
124 :
125 0 : py::array_t<uint16_t> ret(channels_per_daphne * nframes * adcs_per_channel);
126 0 : auto ptr = static_cast<uint16_t*>(ret.request().ptr);
127 0 : for (size_t i=0; i<(size_t)nframes; ++i) {
128 0 : auto fr = reinterpret_cast<fddetdataformats::DAPHNEEthStreamFrame*>(static_cast<char*>(data) + i * sizeof(fddetdataformats::DAPHNEEthStreamFrame));
129 0 : for (size_t j=0; j<adcs_per_channel; ++j)
130 0 : for (size_t k=0; k<channels_per_daphne; ++k)
131 0 : ptr[channels_per_daphne * (adcs_per_channel * i + j) + k] = fr->get_adc(j,k);
132 : }
133 0 : ret.resize({nframes*adcs_per_channel, channels_per_daphne});
134 :
135 0 : return ret;
136 0 : }
137 :
138 : /**
139 : * @brief Unpacks data containing DAPHNEFrames into a numpy array with the
140 : * timestamps with dimension (number of DAPHNEFrames)
141 : * Warning: It doesn't check that nframes is a sensible value (can read out of bounds)
142 : */
143 :
144 0 : py::array_t<uint64_t> np_array_timestamp_data(void* data, int nframes){
145 :
146 0 : py::array_t<uint64_t> ret(nframes);
147 0 : auto ptr = static_cast<uint64_t*>(ret.request().ptr);
148 0 : for (size_t i=0; i<(size_t)nframes; ++i) {
149 0 : auto fr = reinterpret_cast<fddetdataformats::DAPHNEEthFrame*>(static_cast<char*>(data) + i * sizeof(fddetdataformats::DAPHNEEthFrame));
150 0 : ptr[i] = fr->get_timestamp();
151 : }
152 :
153 0 : return ret;
154 0 : }
155 :
156 : /**
157 : * @brief Unpacks data containing DAPHNEStreamFrames into a numpy array with the
158 : * timestamps with dimension (number of DAPHNEStreamFrames)
159 : * Warning: It doesn't check that nframes is a sensible value (can read out of bounds)
160 : */
161 0 : py::array_t<uint64_t> np_array_timestamp_stream_data(void* data, int nframes) {
162 :
163 0 : const auto adcs_per_channel = fddetdataformats::DAPHNEEthStreamFrame::s_adcs_per_channel;
164 0 : const size_t ticks_per_adc = 1;
165 :
166 0 : py::array_t<uint64_t> ret(nframes*adcs_per_channel);
167 :
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::DAPHNEEthStreamFrame*>(static_cast<char*>(data) + i * sizeof(fddetdataformats::DAPHNEEthStreamFrame));
171 0 : for (size_t j=0; j<adcs_per_channel; ++j)
172 0 : ptr[i*adcs_per_channel+j] = fr->get_timestamp()+j*ticks_per_adc;
173 : }
174 :
175 0 : return ret;
176 0 : }
177 :
178 :
179 : /**
180 : * @brief Unpacks a Fragment containing DAPHNEFrames into a numpy array with the
181 : * ADC values and dimension (number of DAPHNEFrames in the Fragment, 320)
182 : */
183 0 : py::array_t<uint16_t> np_array_adc(daqdataformats::Fragment& frag){
184 0 : return np_array_adc_data(frag.get_data(), (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) / sizeof(fddetdataformats::DAPHNEEthFrame));
185 : }
186 :
187 : /**
188 : * @brief Unpacks a Fragment containing DAPHNEStreamFrames into a numpy array with the
189 : * ADC values and dimension (number of DAPHNEStreamFrames in the Fragment, 4)
190 : */
191 0 : py::array_t<uint16_t> np_array_adc_stream(daqdataformats::Fragment& frag){
192 0 : return np_array_adc_stream_data(frag.get_data(), (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) / sizeof(fddetdataformats::DAPHNEEthStreamFrame));
193 : }
194 :
195 :
196 : /**
197 : * @brief Unpacks the timestamps in a Fragment containing WIBFrames into a numpy
198 : * array with dimension (number of DAPHNEFrames in the Fragment)
199 : */
200 0 : py::array_t<uint64_t> np_array_timestamp(daqdataformats::Fragment& frag){
201 0 : return np_array_timestamp_data(frag.get_data(), (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) / sizeof(fddetdataformats::DAPHNEEthFrame));
202 : }
203 :
204 : /**
205 : * @brief Unpacks the timestamps in a Fragment containing DAPHNEStreamFrames into a numpy
206 : * array with dimension (number of DAPHNEStreamFrames in the Fragment)
207 : */
208 0 : py::array_t<uint64_t> np_array_timestamp_stream(daqdataformats::Fragment& frag){
209 0 : return np_array_timestamp_stream_data(frag.get_data(), (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) / sizeof(fddetdataformats::DAPHNEEthStreamFrame));
210 : }
211 :
212 :
213 : } // namespace dunedaq::rawdatautils::daphne // NOLINT
|