Public Member Functions | Private Member Functions | Private Attributes | List of all members
dune::FelixCompressor Class Reference

#include <FelixCompress.hh>

Public Member Functions

 FelixCompressor (const uint8_t *data, const size_t num_frames=10000)
 
 FelixCompressor (const dune::FelixFragment &frag)
 
void store_metadata (std::vector< char > &out)
 
void header_reduce (std::vector< char > &out)
 
void generate_Huff_tree (std::vector< char > &out)
 
void ADC_compress (std::vector< char > &out)
 
void compress_copy (std::vector< char > &out)
 

Private Member Functions

FelixFrame const * frame_ (const size_t &frame_num=0) const
 

Private Attributes

const void * input
 
const size_t input_length
 
const size_t num_frames = input_length / sizeof(FelixFrame)
 
HuffTree hufftree
 

Detailed Description

Definition at line 200 of file FelixCompress.hh.

Constructor & Destructor Documentation

dune::FelixCompressor::FelixCompressor ( const uint8_t *  data,
const size_t  num_frames = 10000 
)
inline
dune::FelixCompressor::FelixCompressor ( const dune::FelixFragment frag)
inline

Definition at line 218 of file FelixCompress.hh.

219  : input(frag.dataBeginBytes()), input_length(frag.dataSizeBytes()) {}
const size_t input_length
size_t dataSizeBytes() const
const uint8_t * dataBeginBytes() const

Member Function Documentation

void dune::FelixCompressor::ADC_compress ( std::vector< char > &  out)
inline

Definition at line 371 of file FelixCompress.hh.

371  {
372  // Resize the output buffer appropriately for the worst case.
373  const size_t tail = out.size();
374  out.resize(tail + sizeof(adc_t) * num_frames * 256);
375  // Record the encoded ADC values into the buffer.
376  unsigned rec_bits = 0;
377  const char* dest = &out[0] + tail;
378 
379  for(unsigned j = 0; j < 256; ++j) {
380  adc_t curr_val = frame_(0)->channel(j);
381  *(unsigned long*)(dest + (rec_bits/8)) |= hufftree(curr_val)->huffcode << (rec_bits%8);
382  rec_bits += hufftree(curr_val)->hufflength;
383 
384  for (unsigned i = 1; i < num_frames; ++i) {
385 #ifdef PREV
386  adc_t curr_val = frame_(i)->channel(j) - frame_(i - 1)->channel(j);
387 #else
388  adc_t curr_val = frame_(i)->channel(j);
389 #endif
390 
391  // No code is longer than 64 bits.
392  *(uint64_t*)(dest + (rec_bits/8)) |= hufftree(curr_val)->huffcode << (rec_bits%8);
393  rec_bits += hufftree(curr_val)->hufflength;
394  }
395  }
396  // Resize output buffer to actual data length.
397  out.resize(tail + rec_bits / 8 + 1);
398  }
uint16_t adc_t
Definition: FelixFormat.hh:18
FelixFrame const * frame_(const size_t &frame_num=0) const
uint16_t channel(const uint8_t block_num, const uint8_t adc, const uint8_t ch) const
Definition: FelixFormat.hh:387
void dune::FelixCompressor::compress_copy ( std::vector< char > &  out)
inline

Definition at line 401 of file FelixCompress.hh.

401  {
402  // auto comp_begin = std::chrono::high_resolution_clock::now();
403  store_metadata(out);
404  // auto meta_end = std::chrono::high_resolution_clock::now();
405  // std::cout << "Meta time taken: "
406  // << std::chrono::duration_cast<std::chrono::microseconds>(
407  // meta_end - comp_begin)
408  // .count()
409  // << " us.\n";
410  header_reduce(out);
411  // auto header_end = std::chrono::high_resolution_clock::now();
412  // std::cout << "Header time taken: "
413  // << std::chrono::duration_cast<std::chrono::microseconds>(
414  // header_end - meta_end)
415  // .count()
416  // << " us.\n";
417  generate_Huff_tree(out);
418  // auto huff_end = std::chrono::high_resolution_clock::now();
419  // std::cout << "Huffman time taken: "
420  // << std::chrono::duration_cast<std::chrono::microseconds>(
421  // huff_end - header_end)
422  // .count()
423  // << " us.\n";
424  ADC_compress(out);
425  // auto adc_end = std::chrono::high_resolution_clock::now();
426  // std::cout << "ADC time taken: "
427  // << std::chrono::duration_cast<std::chrono::microseconds>(
428  // adc_end - huff_end)
429  // .count()
430  // << " us.\n";
431  }
void generate_Huff_tree(std::vector< char > &out)
void header_reduce(std::vector< char > &out)
void store_metadata(std::vector< char > &out)
void ADC_compress(std::vector< char > &out)
FelixFrame const* dune::FelixCompressor::frame_ ( const size_t &  frame_num = 0) const
inlineprivate

Definition at line 208 of file FelixCompress.hh.

208  {
209  return static_cast<FelixFrame const*>(input) + frame_num;
210  }
void dune::FelixCompressor::generate_Huff_tree ( std::vector< char > &  out)
inline

Definition at line 322 of file FelixCompress.hh.

322  {
323  // Build a frequency table.
324  std::unordered_map<adc_t, uint32_t> freq_table;
325  for (unsigned vi = 0; vi < frame_()->num_ch_per_frame; ++vi) {
326  freq_table[frame_(0)->channel(vi)]++;
327  for (unsigned fri = 1; fri < num_frames; ++fri) {
328 #ifdef PREV
329  adc_t curr_val = frame_(fri)->channel(vi) - frame_(fri - 1)->channel(vi);
330 #else
331  adc_t curr_val = frame_(fri)->channel(vi);
332 #endif
333  freq_table[curr_val]++;
334  }
335  }
336 
337  // Save the number of unique values to the metadata.
338  MetaData* meta = reinterpret_cast<MetaData*>(&out[0]);
339  meta->unique_values = freq_table.size();
340 
341  // Save the frequency table to the outgoing buffer so that the decompressor
342  // can make a Huffman tree of its own.
343  size_t tail = out.size();
344  out.resize(tail + freq_table.size() * (sizeof(adc_t) + 4));
345  for (auto p : freq_table) {
346  memcpy(&out[tail], &p.first, sizeof(p.first));
347  memcpy(&out[tail + sizeof(p.first)], &p.second, sizeof(p.second));
348  tail += sizeof(p.first) + sizeof(p.second);
349  }
350 
351  // Insert the frequency table into Huffman tree nodes and calculate the
352  // information entropy according to Shannon.
353  std::vector<HuffTree::Node> nodes;
354  double entropy = 0;
355  const unsigned num_vals = num_frames * frame_()->num_ch_per_frame;
356  for (auto p : freq_table) {
357  HuffTree::Node curr_node;
358  curr_node.value = p.first;
359  curr_node.frequency = p.second;
360  nodes.push_back(curr_node);
361 
362  entropy += (double)p.second / num_vals * log((double)num_vals / p.second);
363  }
364  // std::cout << "ADC value entropy: " << entropy << " bits.\n";
365 
366  // Connect the nodes in the tree according to Huffman's method.
367  hufftree.make_tree(nodes);
368  }
uint16_t adc_t
Definition: FelixFormat.hh:18
static constexpr size_t num_ch_per_frame
Definition: FelixFormat.hh:298
QMapNodeBase Node
Definition: qmap.cpp:41
FelixFrame const * frame_(const size_t &frame_num=0) const
std::unordered_map< uint16_t, Node * > make_tree(std::vector< Node > nodevec)
#define nodes
p
Definition: test.py:223
uint16_t channel(const uint8_t block_num, const uint8_t adc, const uint8_t ch) const
Definition: FelixFormat.hh:387
void dune::FelixCompressor::header_reduce ( std::vector< char > &  out)
inline

Definition at line 233 of file FelixCompress.hh.

233  {
234  // Fields for storing which frames have faulty headers.
235  std::vector<uint8_t> bad_headers(num_frames/8 + 1);
236  // Check all error fields and increments of timestamp and CCC.
237  for (unsigned i = 1; i < num_frames; ++i) {
238  bool check_failed = false;
239 
240  // WIB header checks.
241  check_failed |= frame_()->sof() ^ frame_(i)->sof();
242  check_failed |= frame_()->version() ^ frame_(i)->version();
243  check_failed |= frame_()->fiber_no() ^ frame_(i)->fiber_no();
244  check_failed |= frame_()->crate_no() ^ frame_(i)->crate_no();
245  check_failed |= frame_()->slot_no() ^ frame_(i)->slot_no();
246  check_failed |= frame_()->mm() ^ frame_(i)->mm();
247  check_failed |= frame_()->oos() ^ frame_(i)->oos();
248  check_failed |= frame_()->wib_errors() ^ frame_(i)->wib_errors();
249  check_failed |= frame_()->z() ^ frame_(i)->z();
250 
251  check_failed |=
252  (uint64_t)(frame_()->timestamp() + 25 * i) ^ frame_(i)->timestamp();
253 
254  // COLDATA header checks.
255  for (unsigned j = 0; j < 4; ++j) {
256  check_failed |= frame_()->s1_error(j) ^ frame_(i)->s1_error(j);
257  check_failed |= frame_()->s2_error(j) ^ frame_(i)->s2_error(j);
258  check_failed |= frame_()->checksum_a(j) ^ frame_(i)->checksum_a(j);
259  check_failed |= frame_()->checksum_b(j) ^ frame_(i)->checksum_b(j);
260  check_failed |=
262  for (unsigned h = 0; h < 8; ++h) {
263  check_failed |= frame_()->hdr(j, h) ^ frame_(i)->hdr(j, h);
264  }
265 
266  check_failed |=
267  (uint16_t)(frame_()->coldata_convert_count(j) + 25 * i) ^
269  }
270 
271  // Set a bit if anything failed.
272  if (check_failed) {
273  bad_headers[i/8] |= 1 << (i%8);
274 
275  // std::cout << "Check failed at the " << i << "th frame.\n";
276 
277  // std::cout << "First frame:\n";
278  // frame_(i - 1)->print();
279  // std::cout << "Second frame:\n";
280  // frame_(i)->print();
281 
282  // exit(1);
283  }
284  } // Loop over all frames.
285 
286  // Record faulty frame field.
287  size_t tail = out.size();
288  out.resize(tail + num_frames/8+1);
289  memcpy(&out[tail], &bad_headers[0], bad_headers.size());
290 
291  // Record first headers.
292  tail = out.size();
293  out.resize(tail + sizeof(WIBHeader) + 4*sizeof(ColdataHeader));
294 
295  memcpy(&out[tail], frame_()->wib_header(), sizeof(WIBHeader));
296  memcpy(&out[tail + sizeof(WIBHeader)], frame_()->coldata_header(0),
297  sizeof(ColdataHeader));
298  memcpy(&out[tail + sizeof(WIBHeader) + sizeof(ColdataHeader)], frame_()->coldata_header(1),
299  sizeof(ColdataHeader));
300  memcpy(&out[tail + sizeof(WIBHeader) + 2*sizeof(ColdataHeader)], frame_()->coldata_header(2),
301  sizeof(ColdataHeader));
302  memcpy(&out[tail + sizeof(WIBHeader) + 3*sizeof(ColdataHeader)], frame_()->coldata_header(3),
303  sizeof(ColdataHeader));
304 
305  // Loop over frames again to record faulty headers.
306  for(unsigned i = 1; i < num_frames; ++i) {
307  bool check_failed = (bad_headers[i / 8] >> (7 - (i % 8))) & 1;
308  if(!check_failed) { continue; }
309 
310  tail = out.size();
311  out.resize(tail + sizeof(WIBHeader) + 4*sizeof(ColdataHeader));
312 
313  memcpy(&out[tail], frame_(i)->wib_header(), sizeof(WIBHeader));
314  for(unsigned j = 0; j < 4; ++j) {
315  memcpy(&out[tail + sizeof(WIBHeader)], frame_(i)->coldata_header(j),
316  sizeof(ColdataHeader));
317  }
318  }
319  }
uint8_t hdr(const uint8_t block_num, const uint8_t i) const
Definition: FelixFormat.hh:361
uint8_t version() const
Definition: FelixFormat.hh:310
uint8_t slot_no() const
Definition: FelixFormat.hh:313
FelixFrame const * frame_(const size_t &frame_num=0) const
uint8_t mm() const
Definition: FelixFormat.hh:314
uint8_t sof() const
Definition: FelixFormat.hh:308
uint16_t checksum_b(const uint8_t block_num) const
Definition: FelixFormat.hh:352
uint8_t fiber_no() const
Definition: FelixFormat.hh:311
uint8_t z() const
Definition: FelixFormat.hh:319
uint16_t wib_errors() const
Definition: FelixFormat.hh:316
uint16_t error_register(const uint8_t block_num) const
Definition: FelixFormat.hh:358
uint8_t s2_error(const uint8_t block_num) const
Definition: FelixFormat.hh:346
uint8_t crate_no() const
Definition: FelixFormat.hh:312
uint8_t oos() const
Definition: FelixFormat.hh:315
uint16_t coldata_convert_count(const uint8_t block_num) const
Definition: FelixFormat.hh:355
uint16_t checksum_a(const uint8_t block_num) const
Definition: FelixFormat.hh:349
uint8_t s1_error(const uint8_t block_num) const
Definition: FelixFormat.hh:343
uint64_t timestamp() const
Definition: FelixFormat.hh:317
void dune::FelixCompressor::store_metadata ( std::vector< char > &  out)
inline

Definition at line 222 of file FelixCompress.hh.

222  {
223  // Clear the vector as a first action to make sure there is a clean slate to
224  // work with.
225  out.clear();
226 
227  MetaData meta = {1, 0, (uint32_t)num_frames};
228  out.resize(sizeof(meta));
229  memcpy(&out[0], &meta, sizeof(meta));
230  }

Member Data Documentation

HuffTree dune::FelixCompressor::hufftree
private

Definition at line 213 of file FelixCompress.hh.

const void* dune::FelixCompressor::input
private

Definition at line 203 of file FelixCompress.hh.

const size_t dune::FelixCompressor::input_length
private

Definition at line 204 of file FelixCompress.hh.

const size_t dune::FelixCompressor::num_frames = input_length / sizeof(FelixFrame)
private

Definition at line 205 of file FelixCompress.hh.


The documentation for this class was generated from the following file: