Belle II Software  release-08-01-10
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 
16 using namespace Belle2;
17 using namespace ECL;
18 
19 unsigned 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 
35 void 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 
62 void 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 
97 namespace {
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 
183 void 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 
205 int 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 
227 extern "C" {
232  void e10_31(const double* I, double* O);
233 
238  void e01_31(const double* I, double* O);
239 }
240 
241 ECLDCTCompress::ECLDCTCompress(double scale, double c0, width_t* w): m_scale(scale), m_c0(c0), m_widths(w) {}
242 
243 void 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 
278 ECLCompress* 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