HuffDataCompressor_service.cc
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////////////
2 /////////////////////////////////////////////////////////////////////////////
3 //
4 // Class for compressing ADC data internally represented
5 // as 16 bit unsigned int
6 // Max ADC resolution, however, cannot be greater than 15bits as
7 // 1bit is reserved to signal whether the packet is compressed or not
8 //
9 // The Huffman encoding scheme used here is the one developed by uBooNE
10 //
11 // The basic idea is to handle binnary codes as strings --> maybe not
12 // the most performant, but maybe easier to understand
13 //
14 /////////////////////////////////////////////////////////////////////////////
15 /////////////////////////////////////////////////////////////////////////////
16 #include <iostream>
17 #include <iomanip>
18 #include <sstream>
19 #include <cstdlib>
20 
21 #include "LogMsg.h"
22 #include "HuffDataCompressor.h"
24 
25 using namespace std;
26 using namespace dlardaq;
27 
28 //
29 //
30 //
31 //
32 // ctor (private)
33 HuffDataCompressor::HuffDataCompressor()
34 {
35  // max ADC supported
36 
37  // note that we will use "short" to store either ADC or diff
38  // for 16 bit short goes between -/+ 32767 or 15 bits
39  m_MaxAdcBits = 15; //+1 bit is reserved for compression flag
40 
41  // number of reserved bits
42  m_NbitsHead = 1;
43 
44  // we use 8 bit words on the output
45  m_NbitsByte = 8; //sizeof(BYTE)*8;
46 
47  m_Verbosity = 0;
48 
49  // define encoding map
50  SetEncoding();
51 }
52 
53 
54 //
55 // The Huffman encoding scheme
56 // Needless to say it should not change
57 // between comression/decompression steps
58 //
59 // set encoding system
60 void HuffDataCompressor::SetEncoding()
61 {
62 
63  // basic huffman encoding scheme
64  // same as used by uBooNE
65  std::map<short, std::string> codeMap;
66  codeMap[0] = "1";
67  codeMap[-1] = "01";
68  codeMap[1] = "001";
69  codeMap[-2] = "0001";
70  codeMap[2] = "00001";
71  codeMap[-3] = "000001";
72  codeMap[3] = "0000001";
73 
74  // max difference
75  m_MaxDiff = 3;
76 
77  // 0 no repetion encoding >MaxDiff repetion encoding
78  m_NSeqRep = 4;
79  m_NSeqRepVal = 0;
80  m_SeqEnable = (m_NSeqRep > 0); // && (m_NSeqRep > m_MaxDiff);
81 
82  m_CmMap.clear();
83  m_UCmMap.clear();
84 
85  //
86  m_MinCodeSize = 999;
87  m_MaxCodeSize = 0;
88 
90  for(it = codeMap.begin();it!=codeMap.end();it++)
91  {
92 
93  short deltaval = it->first;
94  string bincode = it->second;
95 
96  if(m_SeqEnable)
97  {
98  // add zeros to nominal huffman codes
99  bincode = "0" + bincode;
100  }
101 
102  size_t codesize = (bincode).size();
103  if(codesize > m_MaxCodeSize)
104  m_MaxCodeSize = codesize;
105  if(codesize < m_MinCodeSize)
106  m_MinCodeSize = codesize;
107 
108  // set code map
109  m_CmMap[deltaval] = bincode;
110  }
111 
112  // run-length encoding enabled
113  if(m_SeqEnable)
114  {
115  m_NSeqRepVal = m_MaxDiff + m_NSeqRep;
116  m_CmMap[m_NSeqRepVal] = "1";
117  //m_UCmMap["1"] = m_NSeqRepVal;
118  m_MinCodeSize = 1;
119  }
120 
121  // !!! m_MinCodeSize should be 1 !!!
122  m_UCmMap.resize( m_MaxCodeSize );
123  for(it = m_CmMap.begin();it!=m_CmMap.end();it++)
124  {
125  short deltaval = it->first;
126  string bincode = it->second;
127  m_UCmMap[bincode.size()-1] = std::make_pair(bincode, deltaval);
128  }
129 }
130 
131 //
132 //
133 //
134 // Print encoding
135 void HuffDataCompressor::PrintEncoding()
136 {
137  cout<<endl<<"Huffman coding scheme: "<<endl;
138 
139 
140  for(size_t i=0;i<m_UCmMap.size();i++)
141  {
142  if(i == 0 && m_SeqEnable)
143  {
144  cout<<setw(10)<<m_UCmMap[i].first
145  <<setw(5)<<m_NSeqRep<<" x no change"
146  <<setw(4)<<i+1<<" bit code length"<<endl;
147 
148  }
149  else
150  {
151  cout<<setw(10)<<m_UCmMap[i].first<<setw(5)<<m_UCmMap[i].second
152  <<setw(4)<<i+1<<" bit code length"<<endl;
153  }
154 
155  }
156 
157  cout<<endl;
158 }
159 
160 
161 
162 
163 //
164 //
165 //
166 // access map to compress
167 std::string HuffDataCompressor::GetCodeFromValue(short val)
168 {
169  string emptystr = "";
170 
171  if(std::abs(val) > m_MaxDiff && val != m_NSeqRepVal)
172  {
173  msg_err<<__FILE__<<", "<<__LINE__<<" the value '"<<val<<"' exceeds range"<<endl;
174  return emptystr;
175  }
176 
178  it = m_CmMap.find( val );
179  if(it != m_CmMap.end())
180  return it->second;
181 
182  //
183  msg_err<<__FILE__<<", "<<__LINE__<<" the value '"<<val<<"' could not be found"<<endl;
184  return emptystr;
185 }
186 
187 
188 //
189 // Internal buffer to store raw adc / adc differences
190 //
191 // Add to huff buffer
192 void HuffDataCompressor::AddToHuffBuffer(short val, bool rawadc)
193 {
195  tmp.value = val;
196  tmp.nrep = 0;
197  tmp.codestr = "";
198 
199  if(!rawadc)
200  tmp.codestr = GetCodeFromValue(val);
201  else
202  {
203  HuffBuffer.push_back( tmp );
204  return;
205  }
206 
207  // check if the last value was the same
208  if( HuffBuffer.back().value == tmp.value &&
209  !HuffBuffer.back().codestr.empty() )
210  {
211  // just increment repetition counter
212  HuffBuffer.back().nrep += 1;
213  }
214  else
215  {
216  // add new entry
217  HuffBuffer.push_back( tmp );
218  }
219 }
220 
221 //
222 //
223 //
224 // get binary string
225 std::string HuffDataCompressor::GetBinaryString(short val, size_t strsize)
226 {
227  std::string s = bitset<16> ( val ).to_string();
228 
229  if(strsize < 16)
230  return s.substr(s.size() - strsize); //crop to required size
231 
232  // ok we have a long string. Why?
233  msg_warn<<__FILE__<<", "<<__LINE__<<" the string looks too long"<<endl;
234  while(s.size() < strsize) s = "0" + s; //pad 0 to front
235  return s;
236 }
237 
238 //
239 //
240 //
241 // set number of ADC bits
242 bool HuffDataCompressor::SetNbitsAdc( short nbadc )
243 {
244  if( nbadc > m_MaxAdcBits ) return false;
245 
246  // this is max bits that can be occupied by data
247  m_NbitsHC = nbadc;
248 
249  // our basic packet size (should not exceed m_MaxAdcBits)
250  m_PacketSize = m_NbitsHC + m_NbitsHead;
251 
252  return true;
253 }
254 
255 //
256 //
257 //
258 // add words to byte buffer keeping track of the remainder
259 // partbyte ("partial byte") contains the remainder string
260 void HuffDataCompressor::AddWordsToByteBuffer(std::string words,
261  std::vector<BYTE> &buf,
262  std::string &partbyte)
263 {
264  if( words.empty() && partbyte.empty() ) return;
265 
266  // nothing to add yet
267  if( words.size() < m_NbitsByte && partbyte.empty() )
268  {
269  partbyte = words;
270  return;
271  }
272 
273  // just pad with 0 and finish
274  if(words.empty() && !partbyte.empty())
275  {
276  // pad partial byte until we get to a full byte
277  while(partbyte.size() < m_NbitsByte) partbyte += "0";
278  buf.push_back( (strtoul(partbyte.c_str(), 0, 2) & 0xff) );
279  partbyte.clear();
280  return;
281  }
282 
283  for(size_t i=0;i<words.size();i++)
284  {
285  if(partbyte.size() == m_NbitsByte)
286  {
287  buf.push_back( (strtoul(partbyte.c_str(), 0, 2) & 0xff) );
288  partbyte.clear();
289  }
290 
291  partbyte += words[i];
292  }
293 }
294 
295 
296 
297 //
298 //
299 //
300 // compress ch data using huffman codes
301 void HuffDataCompressor::CompressChData( short nbadc, std::vector<adc16_t> &raw_in,
302  std::vector<BYTE> &bin_out )
303 {
304  if(!SetNbitsAdc( nbadc ))
305  {
306  bin_out.clear();
307  msg_err<<"ADC "<<nbadc<<" bits exceeds max supported "<<m_MaxAdcBits<<endl;
308  return;
309  }
310 
311 
312  HuffBuffer.clear();
313 
314  // calculate differences and fill our HC buffer
315  short delta;
316  for(size_t i=0;i<raw_in.size();i++)
317  {
318  if(i==0) delta = m_MaxDiff + 1;
319  else delta = raw_in[i] - raw_in[i-1];
320 
321  if(std::abs(delta) > m_MaxDiff) // store uncompressed raw data
322  AddToHuffBuffer( (short)raw_in[i], true );
323  else
324  AddToHuffBuffer( delta, false );
325  }
326 
327 
328  // not defined unless SeqEnable is set
329  string bitrepcode = "";
330  if(m_SeqEnable)
331  {
332  bitrepcode = GetCodeFromValue( m_NSeqRepVal ); //NSeqRep );
333  if(bitrepcode.empty())
334  {
335  msg_err<<__FILE__<<", "<<__LINE__
336  <<" encoding repetion failed. Aborting ..."<<endl;
337  return;
338  }
339  }
340 
341  // now compress stream
342  short nhcrep; //repetition
343  string bitword, bitcode, partbyte;
344  bitword = "";
345  partbyte = ""; // string to hold ramainder of byte
346 
347  for(size_t i=0;i<HuffBuffer.size();i++)
348  {
349 
350  //cout<<i
351  //<<" "<<HuffBuffer[i].value
352  //<<" "<<HuffBuffer[i].nrep;
353  //if( !HuffBuffer[i].codestr.empty() ) cout<<" "<<HuffBuffer[i].codestr<<endl;
354  //else cout<<" rawadc "<<endl;
355 
356  if(HuffBuffer[i].codestr.empty()) //raw adc
357  {
358  // write out whatever we have in the buffer
359  if(bitword.size() > m_NbitsHead) // more than just a header
360  {
361  // pad with zero's to buffer length
362  while(bitword.size() < m_PacketSize) bitword += "0";
363  AddWordsToByteBuffer( bitword, bin_out, partbyte );
364  }
365 
366  // uncompressed data
367  bitword = "0" + GetBinaryString( HuffBuffer[i].value, m_NbitsHC );
368 
369  //
370  AddWordsToByteBuffer( bitword, bin_out, partbyte );
371  bitword = "1";
372  continue;
373  }
374 
375  // compress data
376  bitcode = HuffBuffer[i].codestr;
377  nhcrep = HuffBuffer[i].nrep;
378 
379  for(short jj=0;jj<=nhcrep;jj++)
380  {
381  //
382  if(jj==0)
383  bitword += bitcode;
384  else if(jj+m_NSeqRep <= nhcrep && m_SeqEnable)
385  {
386  bitword += bitrepcode;
387  jj += (m_NSeqRep-1);
388  }
389  else
390  bitword += bitcode;
391 
392 
393  // attempt to write to compresssed stream
394  if(bitword.size() >= m_PacketSize) // check the size
395  {
396  if(bitword.size() == m_PacketSize) //write it out
397  {
398  AddWordsToByteBuffer( bitword, bin_out, partbyte );
399  bitword = "1"; //next iteration of compression
400  }
401  else
402  {
403  // too large for one packet
404  string towrite = bitword.substr(0, m_PacketSize);
405  string tosave = bitword.substr(m_PacketSize);
406 
407  // write out
408  AddWordsToByteBuffer( towrite, bin_out, partbyte );
409 
410  // carry over for next iteration
411  bitword = "1" + tosave;
412  }
413  }
414  } // end for
415 
416  } // end i-loop
417 
418  //cout<<"Last bitword and partial byte"<<bitword<<" "<<partbyte<<endl;
419 
420  // write whatever is left
421  if(bitword.size() > m_NbitsHead) // more than just a header
422  AddWordsToByteBuffer( bitword, bin_out, partbyte );
423 
424  //cout<<"Last partial byte word "<<partbyte<<endl;
425 
426  // write out remaning byte padded with 0s to next byte boundary
427  AddWordsToByteBuffer( "", bin_out, partbyte );
428 }
429 
430 
431 //
432 //
433 //
434 // compress event data using huffman codes
435 void HuffDataCompressor::CompressEventData( short nbadc, size_t nch, size_t seqlen,
436  std::vector<adc16_t> &raw_in,
437  std::vector<BYTE> &bin_out )
438 {
439  bin_out.clear();
440  if(!SetNbitsAdc( nbadc ))
441  {
442  msg_err<<"ADC "<<nbadc<<" bits exceeds max supported "<<m_MaxAdcBits<<endl;
443  return;
444  }
445 
446  if( seqlen * nch != raw_in.size() )
447  {
448  msg_err<<"Length of raw data vector does not match with expected "<<endl;
449  return;
450  }
451 
452  for(size_t i=0;i<nch;i++)
453  {
454  size_t istart = i*seqlen;
455  // get ch data
456  std::vector<adc16_t> chdata(&raw_in[istart], &raw_in[istart+seqlen]);
457  CompressChData( nbadc, chdata, bin_out );
458  }
459 }
460 
461 
462 //
463 //
464 // compress event data using huffman codes
465 void HuffDataCompressor::CompressEventData( short nbadc, size_t nch, size_t seqlen,
466  std::vector< std::vector<adc16_t> > &raw_in,
467  std::vector<BYTE> &bin_out )
468 {
469  bin_out.clear();
470  if(!SetNbitsAdc( nbadc ))
471  {
472  msg_err<<"ADC "<<nbadc<<" bits exceeds max supported "<<m_MaxAdcBits<<endl;
473  return;
474  }
475 
476  if( nch != raw_in.size() )
477  {
478  msg_err<<"Number of ch in raw data vector does not match with expected "<<endl;
479  return;
480  }
481 
482  for(size_t i=0;i<nch;i++)
483  {
484  if( raw_in[i].size() != seqlen )
485  {
486  msg_err<<"No support for compression of unequal sequence lenghts at the moment"<<endl;
487  bin_out.clear();
488  return;
489  }
490 
491  CompressChData( nbadc, raw_in[i], bin_out );
492  }
493 }
494 
495 
496 //
497 //
498 //
499 // decode individual bits from a byte
500 void HuffDataCompressor::ReadNextByte(size_t &byteidx, const char *buf,
501  std::deque<bitset<1> > &bits)
502 {
503  unsigned short bitmask = 1 << (m_NbitsByte - 1);
504 
505  // decode individual bits
506  for(size_t i=0;i<m_NbitsByte;i++)
507  bits.push_back( bitset<1>( (buf[byteidx] & (bitmask >> i)) != 0) );
508 
509  byteidx++;
510 }
511 
512 
513 //
514 //
515 //
516 // decode individual bits from a byte
517 void HuffDataCompressor::ReadNextByte(std::ifstream &fin, std::deque< std::bitset<1> > &bits,
518  bool &status)
519 {
520  status = true;
521  char byteword;
522 
523  if(!fin.get(byteword))
524  {
525  status = false;
526  return;
527  }
528 
529  unsigned short bitmask = 1 << (m_NbitsByte - 1);
530 
531  // decode individual bits
532  for(size_t i=0;i<m_NbitsByte;i++)
533  bits.push_back( bitset<1>( (byteword & (bitmask >> i)) != 0) );
534 }
535 
536 
537 //
538 //
539 //
540 // Decompress event from binary sequence (only single event)
541 //
542 void HuffDataCompressor::DecompressEventData( short nbadc,
543  size_t nch,
544  size_t seqlen,
545  const char *buf, size_t bufsize, size_t &byteidx,
546  std::vector<adc16_t> &adc )
547 {
548  if(!SetNbitsAdc( nbadc ))
549  {
550  msg_err<<"ADC "<<nbadc<<" bits exceeds max supported "<<m_MaxAdcBits<<endl;
551  return;
552  }
553  adc.clear();
554 
555  vector< adc16_t > chdata;
556  deque< bitset<1> > bitqueue;
557 
558  stringstream ss;
559  short lastdelta = -999;
560  size_t bitsread = 0;
561  int noread = 0;
562 
563  size_t chread = 0;
564 
565  byteidx = 0;
566  // basic idea is to read bits one byte at a time from the input buffer
567  // the first entry in the bitqueue deck should always be aligned on the
568  // compressed / raw flag and the deck should contain at least m_PacketSize bits
569  while( adc.size() != nch*seqlen )
570  {
571  if(byteidx<bufsize) ReadNextByte(byteidx, buf, bitqueue);
572  else noread++;
573 
574  if(noread > 1) //loopcounter == 1, we process last bits but not read new byte
575  {
576  msg_err<<"There seems to be a problem with decoding"<<endl
577  <<"Bytes read "<<byteidx<<" out of "<<bufsize<<endl
578  <<"Samples accumulated in this channel "<<chdata.size()<<endl
579  <<"Remaining bits are "<<bitqueue.size()<<" "<<bitqueue.empty()<<endl;
580  break;
581  }
582 
583  //read more bytes if possible
584  if( bitqueue.size() < m_PacketSize && byteidx != bufsize)
585  continue;
586 
587  bool iscomp = bitqueue.front().test(0);
588  bitsread++;
589  bitqueue.pop_front(); // compressed / raw flag
590 
591  if(!iscomp) // uncompressed
592  {
593  ss.str(""); //clear our code string (could carry over from compressed)
594 
595  if( bitqueue.size() < m_NbitsHC )
596  {
597  msg_err<<"Fatal decoding error has been encountered : "<<endl
598  <<" Number of bits in the uncompressed stream should be at least "
599  <<m_NbitsHC<<" the current value is "<<bitqueue.size()<<endl;
600  abort();
601  }
602 
603  size_t bitcounter = 0;
604  while(bitcounter < m_NbitsHC)
605  {
606  ss << bitqueue.front();
607  bitqueue.pop_front();
608  bitcounter++;
609  }
610  bitsread += bitcounter;
611 
612  adc16_t val = ( strtoul(ss.str().c_str(), 0, 2) & 0x7FFF );
613  chdata.push_back( val );
614  ss.str("");
615  }
616  else // handle compressed bits
617  {
618  size_t bitcounter = 0;
619  size_t bitstoread = m_NbitsHC;
620  if( bitqueue.size() < m_NbitsHC )
621  bitstoread = bitqueue.size();
622 
623  while( bitcounter < bitstoread )
624  {
625  ss << bitqueue.front();
626  bitqueue.pop_front();
627  bitcounter++;
628  bitsread++;
629  // check if we have a good code
630  size_t strsize = ss.str().size();
631  if( strsize >= m_MinCodeSize && strsize <= m_MaxCodeSize )
632  {
633  bool ok = (m_UCmMap[strsize-1].first == ss.str());
634  if(!ok) continue; //not a good code
635  short val = m_UCmMap[strsize-1].second;
636 
637  ss.str(""); //reset string code
638 
639 
640  // add to our adc vector
641  if( std::abs(val) <= m_MaxDiff)
642  {
643  adc16_t newval = chdata.back() + val;
644  chdata.push_back( newval );
645  lastdelta = val;
646  }
647  else if(val == m_NSeqRepVal)
648  {
649  for(short j=0;j<m_NSeqRep;j++)
650  {
651  adc16_t newval = chdata.back() + lastdelta; //add same value
652  chdata.push_back( newval );
653  }
654  }
655  }// end of if
656 
657  // we got the whole sequence now
658  if(chdata.size() == seqlen) break;
659 
660  } // end while bitcounter
661  } // end else
662 
663  // check if we finished decoding data for a given channel
664  if(chdata.size() == seqlen)
665  {
666 
667  // calculate number of padded bits to the byte boundary
668  size_t padbits = bitsread % m_NbitsByte;
669  if(padbits > 0) padbits = m_NbitsByte - padbits;
670 
671  if(m_Verbosity > 1)
672  {
673  msg_info<<"Bytes read : "<<byteidx<<endl
674  <<"Bits read : "<<bitsread<<endl
675  <<"Bits to boundary : "<<padbits<<endl
676  <<"Last value : "<<chdata.back()<<" ADC "<<endl;
677  }
678 
679  // error checking
680  if( bitqueue.size() < padbits )
681  {
682  msg_err<<"Fatal decoding error has been encountered : "<<endl
683  <<"Byte boundary does not appear to be valid"<<endl
684  <<"Check that the codes are padded with 0 to the next byte boundary"<<endl;
685  abort();
686  }
687 
688  // remove padded bits
689  while(padbits > 0)
690  {
691  bitqueue.pop_front();
692  padbits--;
693  }
694 
695  // some basic check
696  if(!bitqueue.empty())
697  {
698  if(bitqueue.front().test(0) && chread <= (nch-1) )
699  {
700  msg_err<<"Fatal decoding error had been encounter : "<<endl
701  <<"The first bit of the next ch sequence should always be 0 and not "
702  <<bitqueue.front()<<endl;
703  abort();
704  }
705  }
706 
707  // reset the bitsread counter
708  bitsread = 0;
709 
710  // save channel data
711  adc.insert(adc.end(), chdata.begin(), chdata.end() );
712  chread++;
713  chdata.clear();
714 
715  if(m_Verbosity > 1)
716  cout<<"Decoded "<<adc.size()<<" samples"<<endl<<endl;
717  }
718 
719  // basic consistency check
720  if(chread == nch)
721  {
722  // let's see if we grabbed more bytes than needed
723  if(bitqueue.size() > 0) // should be no more than 8
724  {
725  msg_info<<"Bits remaning in the queue "<<bitqueue.size()<<endl;
726  byteidx--;
727  }
728 
729 
730  if(m_Verbosity > 0)
731  {
732  if(m_Verbosity > 1)
733  msg_info<<"Bits remaning in the queue "<<bitqueue.size()<<endl;
734  msg_info<<"DECOMPRESSED EVENT STATUS: OK "<<endl;
735  }
736 
737  // ok we are done
738  break;
739  }
740  } // end while loop
741 }
742 
743 //
744 //
745 //
746 // Decompress event data from binary file
747 // It IS MANDATORY that the position in the file is
748 // set to the beginning of the event data before calling this function
749 //
750 void HuffDataCompressor::DecompressEventData( std::ifstream &fin,
751  short nbadc,
752  size_t nch,
753  size_t seqlen,
754  std::vector< adc16_t > &adc)
755 {
756  if(!SetNbitsAdc( nbadc ))
757  {
758  msg_err<<"ADC "<<nbadc<<" bits exceeds max supported "<<m_MaxAdcBits<<endl;
759  return;
760  }
761  adc.clear();
762 
763  vector< adc16_t > chdata;
764  deque< bitset<1> > bitqueue;
765 
766  stringstream ss;
767  short lastdelta = -999;
768  size_t byteidx = 0;
769  size_t bitsread = 0;
770 
771  int noread = 0;
772  bool flag;
773 
774  size_t chread = 0;
775 
776  // basic idea is to read bits one byte at a time from the input buffer
777  // the first entry in the bitqueue deck should always be aligned on the
778  // compressed / raw flag and the deck should contain at least m_PacketSize bits
779  while( adc.size() != nch*seqlen )
780  {
781  ReadNextByte(fin, bitqueue, flag);
782  if(!flag) noread++;
783 
784  if(noread > 1) //noread == 1, we process last bits but not read new byte
785  {
786  msg_err<<"There seems to be a problem with decoding"<<endl
787  <<"Samples accumulated in this channel "<<chdata.size()<<endl
788  <<"Remaining bits are "<<bitqueue.size()<<" "<<bitqueue.empty()<<endl;
789  break;
790  }
791 
792  //read more bytes if possible
793  if( bitqueue.size() < m_PacketSize && noread < 1)
794  continue;
795 
796  bool iscomp = bitqueue.front().test(0);
797  bitsread++;
798  bitqueue.pop_front(); // compressed / raw flag
799 
800  if(!iscomp) // uncompressed
801  {
802  ss.str(""); //clear our code string (could carry over from compressed)
803 
804  if( bitqueue.size() < m_NbitsHC )
805  {
806  msg_err<<"Fatal decoding error has been encountered : "<<endl
807  <<"Number of bits in the uncompressed stream should be at least "
808  <<m_NbitsHC<<" the current value is "<<bitqueue.size()<<endl;
809  abort();
810  }
811 
812  size_t bitcounter = 0;
813  while(bitcounter < m_NbitsHC)
814  {
815  ss << bitqueue.front();
816  bitqueue.pop_front();
817  bitcounter++;
818  }
819  bitsread += bitcounter;
820 
821  adc16_t val = ( strtoul(ss.str().c_str(), 0, 2) & 0x7FFF );
822  chdata.push_back( val );
823  ss.str("");
824  }
825  else // handle compressed bits
826  {
827  size_t bitcounter = 0;
828  size_t bitstoread = m_NbitsHC;
829  if( bitqueue.size() < m_NbitsHC )
830  bitstoread = bitqueue.size();
831 
832  while( bitcounter < bitstoread )
833  {
834  ss << bitqueue.front();
835  bitqueue.pop_front();
836  bitcounter++;
837  bitsread++;
838  // check if we have a good code
839  size_t strsize = ss.str().size();
840  if( strsize >= m_MinCodeSize && strsize <= m_MaxCodeSize )
841  {
842  bool ok = (m_UCmMap[strsize-1].first == ss.str());
843  if(!ok) continue; //not a good code
844  short val = m_UCmMap[strsize-1].second;
845 
846  // otherwise reset the code
847  ss.str(""); //reset string code
848 
849  // add to our adc vector
850  if( std::abs(val) <= m_MaxDiff)
851  {
852  adc16_t newval = chdata.back() + val;
853  chdata.push_back( newval );
854  lastdelta = val;
855  }
856  else if(val == m_NSeqRepVal)
857  {
858  for(short j=0;j<m_NSeqRep;j++)
859  {
860  adc16_t newval = chdata.back() + lastdelta; //add same value
861  chdata.push_back( newval );
862  }
863  }
864  }// end of if
865 
866  // we got the whole sequence now
867  if(chdata.size() == seqlen) break;
868 
869  } // end while bitcounter
870  } // end else
871 
872  // check if we finished decoding data for a given channel
873  if(chdata.size() == seqlen)
874  {
875 
876  // calculate number of padded bits to the byte boundary
877  size_t padbits = bitsread % m_NbitsByte;
878  if(padbits > 0) padbits = m_NbitsByte - padbits;
879 
880  if(m_Verbosity > 1)
881  {
882  msg_info<<"Bytes read : "<<byteidx<<endl
883  <<"Bits read : "<<bitsread<<endl
884  <<"Bits to boundary : "<<padbits<<endl
885  <<"Last value : "<<chdata.back()<<" ADC "<<endl;
886  }
887 
888  // error checking
889  if( bitqueue.size() < padbits )
890  {
891  msg_err<<"Fatal decoding error has been encountered : "<<endl
892  <<" Byte boundary does not appear to be valid"<<endl
893  <<" Check that the codes are padded with 0 to the next byte boundary"<<endl;
894  abort();
895  }
896 
897  // remove padded bits
898  while(padbits > 0)
899  {
900  bitqueue.pop_front();
901  padbits--;
902  }
903 
904  // some basic check
905  if(!bitqueue.empty())
906  {
907  if(bitqueue.front().test(0) && chread <= (nch-1) )
908  {
909  msg_err<<"Fatal decoding error had been encounter : "<<endl
910  <<" The first bit of the next ch sequence should always be 0 and not "
911  <<bitqueue.front()<<endl;
912  abort();
913  }
914  }
915 
916  // reset the bitsread counter
917  bitsread = 0;
918 
919  // save channel data
920  adc.insert(adc.end(), chdata.begin(), chdata.end() );
921  chread++;
922  chdata.clear();
923 
924  if(m_Verbosity > 1)
925  msg_info<<"Decoded "<<adc.size()<<" samples"<<endl<<endl;
926  }
927 
928  // basic consistency check
929  if(chread == nch)
930  {
931  // let's see if we grabbed more bytes than needed
932  if(bitqueue.size() > 0) // should be no more than 8
933  {
934  msg_info<<"Bits remaning in the queue "<<bitqueue.size()<<endl;
935  msg_info<<"Current position in file "<<fin.tellg();
936  fin.seekg( -1, std::ios::cur );
937  msg_info<<" Prv position in the file "<<fin.tellg()<<endl;
938  }
939 
940 
941  if(m_Verbosity > 0)
942  {
943  if(m_Verbosity > 1)
944  msg_info<<"Bits remaning in the queue "<<bitqueue.size()<<endl;
945  msg_info<<"DECOMPRESSED EVENT STATUS: OK "<<endl;
946  }
947 
948  // ok we are done
949  break;
950  }
951 
952  } // end while
953 }
intermediate_table::iterator iterator
uint16_t adc16_t
Definition: dlardaq.h:40
static LogStream msg_warn(std::cout, _strwarn)
std::string string
Definition: nybbler.cc:12
struct vector vector
int16_t adc
Definition: CRTFragment.hh:202
STL namespace.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
T abs(T value)
string tmp
Definition: languages.py:63
Q_EXPORT QTSManip setw(int w)
Definition: qtextstream.h:331
static LogStream msg_info(std::cout, _strinfo)
static LogStream msg_err(std::cerr, _strerror)
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
static QCString * s
Definition: config.cpp:1042
QTextStream & endl(QTextStream &s)