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