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 "fddetdataformats/DAPHNEFrame.hpp"
10 : #include "fddetdataformats/DAPHNEStreamFrame.hpp"
11 : #include "daqdataformats/Fragment.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 0 : uint32_t get_n_frames(daqdataformats::Fragment const& frag){
23 0 : return (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) / sizeof(fddetdataformats::DAPHNEFrame);
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::DAPHNEStreamFrame);
31 : }
32 :
33 :
34 : /**
35 : * @brief Unpacks channel numbers for DAPHNEStreamFrames 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::DAPHNEStreamFrame::s_channels_per_frame;
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::DAPHNEStreamFrame*>(static_cast<char*>(data) + i * sizeof(fddetdataformats::DAPHNEStreamFrame));
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::DAPHNEFrame*>(static_cast<char*>(data) + i * sizeof(fddetdataformats::DAPHNEFrame));
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::DAPHNEFrame));
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::DAPHNEStreamFrame));
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::DAPHNEFrame::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::DAPHNEFrame*>(static_cast<char*>(data) + i * sizeof(fddetdataformats::DAPHNEFrame));
103 : //auto fr = reinterpret_cast<fddetdataformats::DAPHNEFrame*>(static_cast<char*>(data) + i * sizeof(fddetdataformats::DAPHNEFrame));
104 0 : for (size_t j=0; j<adcs_per_channel; ++j) {
105 0 : ptr[i*adcs_per_channel + j] = fr->get_adc(j);
106 : }
107 : //for (size_t j=0; j<channels_per_daphne; ++j)
108 :
109 : }
110 0 : ret.resize({nframes, adcs_per_channel});
111 :
112 0 : return ret;
113 0 : }
114 :
115 : /**
116 : * @brief Unpacks data containing DAPHNEStreamFrames into a numpy array with the ADC
117 : * values and dimension (number of DAPHNEStreamFrames * adcs_per_channel (64), channels_per_frame (4))
118 : * Warning: It doesn't check that nframes is a sensible value (can read out of bounds)
119 : */
120 0 : py::array_t<uint16_t> np_array_adc_stream_data(void* data, int nframes){
121 :
122 0 : const auto channels_per_daphne = fddetdataformats::DAPHNEStreamFrame::s_channels_per_frame;
123 0 : const auto adcs_per_channel = fddetdataformats::DAPHNEStreamFrame::s_adcs_per_channel;
124 :
125 :
126 0 : py::array_t<uint16_t> ret(channels_per_daphne * nframes * adcs_per_channel);
127 0 : auto ptr = static_cast<uint16_t*>(ret.request().ptr);
128 0 : for (size_t i=0; i<(size_t)nframes; ++i) {
129 0 : auto fr = reinterpret_cast<fddetdataformats::DAPHNEStreamFrame*>(static_cast<char*>(data) + i * sizeof(fddetdataformats::DAPHNEStreamFrame));
130 0 : for (size_t j=0; j<adcs_per_channel; ++j)
131 0 : for (size_t k=0; k<channels_per_daphne; ++k)
132 0 : ptr[channels_per_daphne * (adcs_per_channel * i + j) + k] = fr->get_adc(j,k);
133 : }
134 0 : ret.resize({nframes*adcs_per_channel, channels_per_daphne});
135 :
136 0 : return ret;
137 0 : }
138 :
139 : /**
140 : * @brief Unpacks data containing DAPHNEFrames into a numpy array with the
141 : * timestamps with dimension (number of DAPHNEFrames)
142 : * Warning: It doesn't check that nframes is a sensible value (can read out of bounds)
143 : */
144 :
145 0 : py::array_t<uint64_t> np_array_timestamp_data(void* data, int nframes){
146 :
147 0 : py::array_t<uint64_t> ret(nframes);
148 0 : auto ptr = static_cast<uint64_t*>(ret.request().ptr);
149 0 : for (size_t i=0; i<(size_t)nframes; ++i) {
150 0 : auto fr = reinterpret_cast<fddetdataformats::DAPHNEFrame*>(static_cast<char*>(data) + i * sizeof(fddetdataformats::DAPHNEFrame));
151 0 : ptr[i] = fr->get_timestamp();
152 : }
153 :
154 0 : return ret;
155 0 : }
156 :
157 : /**
158 : * @brief Unpacks data containing DAPHNEStreamFrames into a numpy array with the
159 : * timestamps with dimension (number of DAPHNEStreamFrames)
160 : * Warning: It doesn't check that nframes is a sensible value (can read out of bounds)
161 : */
162 0 : py::array_t<uint64_t> np_array_timestamp_stream_data(void* data, int nframes) {
163 :
164 0 : const auto adcs_per_channel = fddetdataformats::DAPHNEStreamFrame::s_adcs_per_channel;
165 0 : const size_t ticks_per_adc = 1;
166 :
167 0 : py::array_t<uint64_t> ret(nframes*adcs_per_channel);
168 :
169 0 : auto ptr = static_cast<uint64_t*>(ret.request().ptr);
170 0 : for (size_t i=0; i<(size_t)nframes; ++i) {
171 0 : auto fr = reinterpret_cast<fddetdataformats::DAPHNEStreamFrame*>(static_cast<char*>(data) + i * sizeof(fddetdataformats::DAPHNEStreamFrame));
172 0 : for (size_t j=0; j<adcs_per_channel; ++j)
173 0 : ptr[i*adcs_per_channel+j] = fr->get_timestamp()+j*ticks_per_adc;
174 : }
175 :
176 0 : return ret;
177 0 : }
178 :
179 :
180 : /**
181 : * @brief Unpacks a Fragment containing DAPHNEFrames into a numpy array with the
182 : * ADC values and dimension (number of DAPHNEFrames in the Fragment, 320)
183 : */
184 0 : py::array_t<uint16_t> np_array_adc(daqdataformats::Fragment& frag){
185 0 : return np_array_adc_data(frag.get_data(), (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) / sizeof(fddetdataformats::DAPHNEFrame));
186 : }
187 :
188 : /**
189 : * @brief Unpacks a Fragment containing DAPHNEStreamFrames into a numpy array with the
190 : * ADC values and dimension (number of DAPHNEStreamFrames in the Fragment, 4)
191 : */
192 0 : py::array_t<uint16_t> np_array_adc_stream(daqdataformats::Fragment& frag){
193 0 : return np_array_adc_stream_data(frag.get_data(), (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) / sizeof(fddetdataformats::DAPHNEStreamFrame));
194 : }
195 :
196 :
197 : /**
198 : * @brief Unpacks the timestamps in a Fragment containing WIBFrames into a numpy
199 : * array with dimension (number of DAPHNEFrames in the Fragment)
200 : */
201 0 : py::array_t<uint64_t> np_array_timestamp(daqdataformats::Fragment& frag){
202 0 : return np_array_timestamp_data(frag.get_data(), (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) / sizeof(fddetdataformats::DAPHNEFrame));
203 : }
204 :
205 : /**
206 : * @brief Unpacks the timestamps in a Fragment containing DAPHNEStreamFrames into a numpy
207 : * array with dimension (number of DAPHNEStreamFrames in the Fragment)
208 : */
209 0 : py::array_t<uint64_t> np_array_timestamp_stream(daqdataformats::Fragment& frag){
210 0 : return np_array_timestamp_stream_data(frag.get_data(), (frag.get_size() - sizeof(daqdataformats::FragmentHeader)) / sizeof(fddetdataformats::DAPHNEStreamFrame));
211 : }
212 :
213 :
214 : } // namespace dunedaq::rawdatautils::daphne // NOLINT
|