Belle II Software development
ECLCompress.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <ecl/digitization/BitStream.h>
10#include <ecl/digitization/ECLCompress.h>
11#include <ecl/digitization/EclConfiguration.h>
12
13#include <algorithm>
14#include <math.h>
15
16using namespace Belle2;
17using namespace ECL;
18
19unsigned int Belle2::ECL::ilog2(unsigned int v) // find the log base 2 of 32-bit v
20{
21 static const unsigned char MultiplyDeBruijnBitPosition[32] = {
22 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
23 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
24 };
25
26 v |= v >> 1; // first round down to one less than a power of 2
27 v |= v >> 2;
28 v |= v >> 4;
29 v |= v >> 8;
30 v |= v >> 16;
31
32 return MultiplyDeBruijnBitPosition[(v * 0x07C4ACDDU) >> 27];
33}
34
35void ECLBaseCompress::compress(BitStream& out, const int* adc)
36{
37 int amin = adc[0], amax = adc[0];
38 for (unsigned int i = 0; i < EclConfiguration::m_nsmp; i++) {
39 amax = std::max(amax, adc[i]);
40 amin = std::min(amin, adc[i]);
41 }
42
43 amin &= 0x3ffff;
44 out.putNBits(amin, 18);
45 unsigned int w = ilog2(amax - amin) + 1;
46 w &= 0x1f;
47 out.putNBits(w, 5);
48
49 for (unsigned int i = 0; i < EclConfiguration::m_nsmp; i++) {
50 unsigned int d = adc[i] - amin;
51 out.putNBits(d, w);
52 }
53}
54
56{
57 unsigned int amin = out.getNBits(18), w = out.getNBits(5);
58 for (unsigned int i = 0; i < EclConfiguration::m_nsmp; i++)
59 adc[i] = amin + out.getNBits(w);
60}
61
62void ECLDeltaCompress::compress(BitStream& out, const int* adc)
63{
64 int a0 = adc[0], dmin = 0, dmax = 0;
65 for (int k = 1; k < EclConfiguration::m_nsmp; k++) {
66 int d = adc[k] - a0;
67 dmin = std::min(dmin, d);
68 dmax = std::max(dmax, d);
69 a0 = adc[k];
70 }
71
72 unsigned int w = ilog2(std::max(2 * dmax, -2 * dmin)) + 1;
73 w &= 0xf;
74 out.putNBits(w, 4);
75
76 a0 = adc[0] & 0x3ffff;
77 out.putNBits(a0, 18);
78
79 unsigned int base = 1 << (w - 1);
80 for (unsigned int i = 1; i < EclConfiguration::m_nsmp; i++) {
81 unsigned int d = int(adc[i]) - a0 + base;
82 out.putNBits(d, w);
83 a0 = adc[i];
84 }
85}
86
88{
89 unsigned int w = out.getNBits(4);
90 adc[0] = out.getNBits(18);
91 unsigned int base = 1 << (w - 1);
92 for (unsigned int i = 1; i < EclConfiguration::m_nsmp; i++) {
93 adc[i] = adc[i - 1] + out.getNBits(w) - base;
94 }
95}
96
97namespace {
103 width_t widths_scale025[] = {
104 {7, 9, 18, 32},// 7.72447
105 {5, 7, 18, 32},// 5.45839
106 {5, 7, 18, 32},// 5.41033
107 {5, 7, 18, 32},// 5.32805
108 {5, 7, 18, 32},// 5.24319
109 {4, 6, 18, 32},// 5.01064
110 {4, 6, 18, 32},// 4.75667
111 {4, 6, 18, 32},// 4.53016
112 {4, 6, 18, 32},// 4.33823
113 {3, 5, 18, 32},// 4.08838
114 {3, 5, 18, 32},// 3.7205
115 {3, 4, 18, 32},// 3.41795
116 {2, 4, 18, 32},// 3.17582
117 {2, 4, 18, 32},// 2.76922
118 {2, 3, 18, 32},// 2.42437
119 {2, 3, 18, 32},// 2.20985
120 {2, 3, 18, 32},// 2.09761
121 {2, 3, 18, 32},// 2.04576
122 {2, 3, 18, 32},// 2.02288
123 {2, 4, 18, 32},// 2.01152
124 {2, 4, 18, 32},// 2.00643
125 {2, 4, 18, 32},// 2.00386
126 {2, 4, 18, 32},// 2.00244
127 {2, 4, 18, 32},// 2.00171
128 {2, 4, 18, 32},// 2.0012
129 {2, 4, 18, 32},// 2.00081
130 {2, 4, 18, 32},// 2.00055
131 {2, 4, 18, 32},// 2.00036
132 {2, 4, 18, 32},// 2.00023
133 {2, 3, 18, 32},// 2.00012
134 {2, 3, 18, 32} // 2.00004
135 };
136
142 width_t widths_phs2_scale10[] = {
143 {5, 7, 9, 32},// 5.82104
144 {4, 6, 8, 32},// 4.76806
145 {4, 6, 8, 32},// 4.70815
146 {4, 6, 8, 32},// 4.61517
147 {3, 5, 7, 32},// 4.42656
148 {3, 5, 7, 32},// 4.22157
149 {3, 5, 7, 32},// 4.01412
150 {3, 5, 7, 32},// 3.80959
151 {2, 4, 6, 32},// 3.60224
152 {2, 4, 6, 32},// 3.31705
153 {2, 4, 6, 32},// 3.03457
154 {2, 3, 5, 32},// 2.71501
155 {2, 3, 5, 32},// 2.45094
156 {2, 3, 5, 32},// 2.25788
157 {2, 3, 5, 32},// 2.13303
158 {2, 3, 5, 32},// 2.06428
159 {2, 3, 5, 32},// 2.02847
160 {2, 3, 5, 32},// 2.01253
161 {1, 2, 4, 32},// 1.86085
162 {1, 2, 4, 32},// 1.68465
163 {1, 2, 4, 32},// 1.53003
164 {1, 2, 4, 32},// 1.38031
165 {1, 2, 4, 32},// 1.27103
166 {1, 2, 4, 32},// 1.18264
167 {1, 2, 4, 32},// 1.11546
168 {1, 2, 4, 32},// 1.07223
169 {1, 2, 4, 32},// 1.04641
170 {1, 2, 4, 32},// 1.03003
171 {1, 2, 4, 32},// 1.01772
172 {1, 2, 3, 32},// 1.01304
173 {1, 2, 4, 32},// 1.0107
174 };
175}
176
183void stream_int(BitStream& OUT, int x, const width_t& w)
184{
185 int ax = abs(x), m0 = 1 << (w.w0 - 1), m1 = 1 << (w.w1 - 1), m2 = 1 << (w.w2 - 1);
186 if (ax < m0) { // integer fits into w0 bits
187 OUT.putNBits(x, w.w0);
188 } else if (ax < m1) {// integer fits into w1 bits
189 OUT.putNBits((x << w.w0) | m0, w.w1 + w.w0); // first stream prefix showing that we are switching to the next bit width format
190 } else if (ax < m2) {// integer fits into w2 bits
191 OUT.putNBits((m1 << w.w0) | m0, w.w1 + w.w0);
192 OUT.putNBits(x, w.w2);
193 } else {// integer fits into w3 bits
194 OUT.putNBits((m1 << w.w0) | m0, w.w1 + w.w0);
195 OUT.putNBits(m2, w.w2);
196 OUT.putNBits(x, w.w3);
197 }
198}
199
205int fetch_int(BitStream& IN, const width_t& w)
206{
207 int m0 = 1 << (w.w0 - 1), m1 = 1 << (w.w1 - 1), m2 = 1 << (w.w2 - 1);
208 int t = IN.getNBits(w.w0);
209 if (t == m0) {
210 t = IN.getNBits(w.w1);
211 if (t == m1) {
212 t = IN.getNBits(w.w2);
213 if (t == m2) {
214 t = IN.getNBits(w.w3);
215 } else {
216 t = (t << (32 - w.w2)) >> (32 - w.w2);
217 }
218 } else {
219 t = (t << (32 - w.w1)) >> (32 - w.w1);
220 }
221 } else {
222 t = (t << (32 - w.w0)) >> (32 - w.w0);
223 }
224 return t;
225}
226
227extern "C" {
232 void e10_31(const double* I, double* O);
233
238 void e01_31(const double* I, double* O);
239}
240
241ECLDCTCompress::ECLDCTCompress(double scale, double c0, width_t* w): m_scale(scale), m_c0(c0), m_widths(w) {}
242
243void ECLDCTCompress::compress(BitStream& OUT, const int* a)
244{
245 const int N = EclConfiguration::m_nsmp;
246 double buf[N], out[N];
247 for (int k = 0; k < N; k++) buf[k] = a[k];
248 e10_31(buf, out);
249 for (int k = 0; k < N; k++) out[k] *= 1.0 / (2 * N);
250
251 int km = N;
252 for (; km > 16; --km) if (lrint(out[km - 1]*m_scale) != 0) break;
253 OUT.putNBits(N - km, 4);
254 out[0] -= m_c0;
255 for (int k = 0; k < km; k++) {
256 int t = lrint(out[k] * m_scale);
257 stream_int(OUT, t, m_widths[k]);
258 }
259}
260
262{
263 const double iscale = 1 / m_scale;
264 const int N = EclConfiguration::m_nsmp;
265 int nz = in.getNBits(4);
266 for (int i = 0; i < N - nz; i++) adc[i] = fetch_int(in, m_widths[i]);
267 for (int i = N - nz; i < N; i++) adc[i] = 0;
268
269 double c[N], out[N];
270 for (int k = 0; k < N; k++) c[k] = adc[k] * iscale;
271 c[0] += m_c0;
272
273 e01_31(c, out);
274
275 for (int k = 0; k < N; k++) adc[k] = lrint(out[k]);
276}
277
278ECLCompress* Belle2::ECL::selectAlgo(int compAlgo)
279{
280 ECLCompress* comp = nullptr;
281 if (compAlgo == 1) {
282 comp = new ECLBaseCompress;
283 } else if (compAlgo == 2) {
284 comp = new ECLDeltaCompress;
285 } else if (compAlgo == 3) {
286 comp = new ECLDCTCompress(1, 3012, widths_phs2_scale10);
287 } else if (compAlgo == 4) {
288 comp = new ECLDCTCompress(0.25, 3144, widths_scale025);
289 }
290 return comp;
291}
void e01_31(const R *I, R *O)
DCT-III or "the inverse" DCT transformation of 31-point signal This function contains 320 FP addition...
void e10_31(const R *I, R *O)
DCT-II or "the" DCT transformation of 31-point signal This function contains 320 FP additions,...
Bit stream struct.
Definition: BitStream.h:19
unsigned int getNBits(unsigned int n)
Fetch n bits.
Definition: BitStream.h:52
void putNBits(unsigned int value, unsigned int n)
Push n least significant bits of "value" to the stream.
Definition: BitStream.h:37
ECL waveform compression/decompression to/from the BitStream storage with the BASE algorithm.
Definition: ECLCompress.h:60
void compress(BitStream &out, const int *adc) override
Compress the ECL waveform.
Definition: ECLCompress.cc:35
void uncompress(BitStream &out, int *adc) override
Decompress the ECL waveform.
Definition: ECLCompress.cc:55
Abstract class (interface) for ECL waveform compression/decompression to/from the BitStream storage.
Definition: ECLCompress.h:39
ECL waveform compression/decompression to/from the BitStream storage based on the Discrete Cosine Tra...
Definition: ECLCompress.h:84
const width_t * m_widths
Bit widths for the DCT coefficients for prefix encoding.
Definition: ECLCompress.h:103
ECLDCTCompress(double scale, double c0, width_t *w)
Constructor for DCT based compression algorithm.
Definition: ECLCompress.cc:241
void compress(BitStream &out, const int *adc) override
function to compress
Definition: ECLCompress.cc:243
const double m_scale
Scale factor for quantization.
Definition: ECLCompress.h:101
const double m_c0
Average waveform amplitude.
Definition: ECLCompress.h:102
void uncompress(BitStream &in, int *adc) override
function to decompress
Definition: ECLCompress.cc:261
ECL waveform compression/decompression to/from the BitStream storage with the DELTA algorithm.
Definition: ECLCompress.h:69
void compress(BitStream &out, const int *adc) override
function to compress the ECL waveform with the DELTA algorithm
Definition: ECLCompress.cc:62
void uncompress(BitStream &out, int *adc) override
function to decompress the ECL waveform with the DELTA algorithm
Definition: ECLCompress.cc:87
static constexpr int m_nsmp
number of ADC measurements for signal fitting
Abstract base class for different kinds of events.
Bit widths for the prefix coding to encode integers which are mainly concentrated around zero and pro...
Definition: ECLCompress.h:29