CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
AnalysisDescriptions.cc
Go to the documentation of this file.
1 // Last commit: $Id: AnalysisDescriptions.cc,v 1.13 2009/04/06 16:57:28 lowette Exp $
2 // Latest tag: $Name: CMSSW_5_3_11_patch3 $
3 // Location: $Source: /local/reps/CMSSW/CMSSW/OnlineDB/SiStripConfigDb/src/AnalysisDescriptions.cc,v $
4 
8 
9 using namespace std;
10 using namespace sistrip;
11 
12 // -----------------------------------------------------------------------------
24  std::string partition ) {
25 
26  // Check
27  if ( ( !dbParams_.usingDbCache() && !deviceFactory(__func__) ) ||
28  ( dbParams_.usingDbCache() && !databaseCache(__func__) ) ) {
29  return analyses_.emptyRange();
30  }
31 
32  try {
33 
34  if ( !dbParams_.usingDbCache() ) {
35 
36  SiStripDbParams::SiStripPartitions::const_iterator iter = dbParams_.partitions().begin();
37  SiStripDbParams::SiStripPartitions::const_iterator jter = dbParams_.partitions().end();
38  for ( ; iter != jter; ++iter ) {
39 
40  if ( partition == "" || partition == iter->second.partitionName() ) {
41 
42  if ( iter->second.partitionName() == SiStripPartition::defaultPartitionName_ ) { continue; }
43 
44  AnalysisDescriptionsRange range = analyses_.find( iter->second.partitionName() );
45  if ( range == analyses_.emptyRange() ) {
46 
48  if ( analysis_type == AnalysisDescription::T_ANALYSIS_FASTFEDCABLING ) {
49  tmp1 = deviceFactory(__func__)->getAnalysisHistory( iter->second.partitionName(),
50  iter->second.fastCablingVersion().first,
51  iter->second.fastCablingVersion().second,
52  analysis_type );
53  } else if ( analysis_type == AnalysisDescription::T_ANALYSIS_TIMING ) {
54  tmp1 = deviceFactory(__func__)->getAnalysisHistory( iter->second.partitionName(),
55  iter->second.apvTimingVersion().first,
56  iter->second.apvTimingVersion().second,
57  analysis_type );
58  } else if ( analysis_type == AnalysisDescription::T_ANALYSIS_OPTOSCAN ) {
59  tmp1 = deviceFactory(__func__)->getAnalysisHistory( iter->second.partitionName(),
60  iter->second.optoScanVersion().first,
61  iter->second.optoScanVersion().second,
62  analysis_type );
63  } else if ( analysis_type == AnalysisDescription::T_ANALYSIS_VPSPSCAN ) {
64  tmp1 = deviceFactory(__func__)->getAnalysisHistory( iter->second.partitionName(),
65  iter->second.vpspScanVersion().first,
66  iter->second.vpspScanVersion().second,
67  analysis_type );
68  } else if ( analysis_type == AnalysisDescription::T_ANALYSIS_CALIBRATION ) {
69  tmp1 = deviceFactory(__func__)->getAnalysisHistory( iter->second.partitionName(),
70  iter->second.apvCalibVersion().first,
71  iter->second.apvCalibVersion().second,
72  analysis_type );
73  } else if ( analysis_type == AnalysisDescription::T_ANALYSIS_PEDESTALS ) {
74  tmp1 = deviceFactory(__func__)->getAnalysisHistory( iter->second.partitionName(),
75  iter->second.pedestalsVersion().first,
76  iter->second.pedestalsVersion().second,
77  analysis_type );
78  } else if ( analysis_type == AnalysisDescription::T_ANALYSIS_APVLATENCY ) {
79  tmp1 = deviceFactory(__func__)->getAnalysisHistory( iter->second.partitionName(),
80  iter->second.apvLatencyVersion().first,
81  iter->second.apvLatencyVersion().second,
82  analysis_type );
83  } else if ( analysis_type == AnalysisDescription::T_ANALYSIS_FINEDELAY ) {
84  tmp1 = deviceFactory(__func__)->getAnalysisHistory( iter->second.partitionName(),
85  iter->second.fineDelayVersion().first,
86  iter->second.fineDelayVersion().second,
87  analysis_type );
88  } else {
89  std::stringstream ss;
90  ss << "[SiStripConfigDb::" << __func__ << "]"
91  << " Unexpected analysis type \""
92  << analysisType( analysis_type )
93  << "\"! Aborting download...";
94  edm::LogWarning(mlConfigDb_) << ss.str();
95  return analyses_.emptyRange();
96  }
97 
98  // Make local copy
100  CommissioningAnalysisFactory::vectorCopy( tmp1, tmp2 );
101 
102  // Add to cache
103  analyses_.loadNext( iter->second.partitionName(), tmp2 );
104 
105  // Some debug
106  AnalysisDescriptionsRange anals = analyses_.find( iter->second.partitionName() );
107  std::stringstream ss;
108  ss << "[SiStripConfigDb::" << __func__ << "]"
109  << " Downloaded " << anals.size()
110  << " analysis descriptions of type \""
111  << analysisType( analysis_type )
112  << "\" to local cache for partition \""
113  << iter->second.partitionName() << "\"" << std::endl;
114  ss << "[SiStripConfigDb::" << __func__ << "]"
115  << " Cache holds analysis descriptions for "
116  << analyses_.size() << " partitions.";
117  LogTrace(mlConfigDb_) << ss.str();
118 
119  }
120  }
121  }
122 
123  } else { // Use database cache
124  std::stringstream ss;
125  ss << "[SiStripConfigDb::" << __func__ << "]"
126  << " No database cache for analysis objects!";
127  edm::LogWarning(mlConfigDb_) << ss.str();
128  }
129 
130  } catch (...) { handleException( __func__ ); }
131 
132  // Create range object
133  uint16_t np = 0;
134  uint16_t nc = 0;
135  AnalysisDescriptionsRange anals = analyses_.emptyRange();
136  if ( partition != "" ) {
137  anals = analyses_.find( partition );
138  np = 1;
139  nc = anals.size();
140  } else {
141  if ( !analyses_.empty() ) {
142  anals = AnalysisDescriptionsRange( analyses_.find( dbParams_.partitions().begin()->second.partitionName() ).begin(),
143  analyses_.find( (--(dbParams_.partitions().end()))->second.partitionName() ).end() );
144  } else { anals = analyses_.emptyRange(); }
145  np = analyses_.size();
146  nc = anals.size();
147  }
148 
149  stringstream ss;
150  ss << "[SiStripConfigDb::" << __func__ << "]"
151  << " Found " << nc << " analysis descriptions";
152  if ( !dbParams_.usingDbCache() ) { ss << " in " << np << " database partition(s)"; }
153  else { ss << " from shared memory name '" << dbParams_.sharedMemory() << "'"; }
154  if ( analyses_.empty() ) { edm::LogWarning(mlConfigDb_) << ss.str(); }
155  else { LogTrace(mlConfigDb_) << ss.str(); }
156 
157  return anals;
158 
159 }
160 
161 // -----------------------------------------------------------------------------
162 //
164 
165  if ( !deviceFactory(__func__) ) { return; }
166 
167  if ( partition.empty() ) {
168  stringstream ss;
169  ss << "[SiStripConfigDb::" << __func__ << "]"
170  << " Partition string is empty,"
171  << " therefore cannot add analysis descriptions to local cache!";
172  edm::LogWarning(mlConfigDb_) << ss.str();
173  return;
174  }
175 
176  if ( anals.empty() ) {
177  stringstream ss;
178  ss << "[SiStripConfigDb::" << __func__ << "]"
179  << " Vector of analysis descriptions is empty,"
180  << " therefore cannot add analysis descriptions to local cache!";
181  edm::LogWarning(mlConfigDb_) << ss.str();
182  return;
183  }
184 
185  SiStripDbParams::SiStripPartitions::const_iterator iter = dbParams_.partitions().begin();
186  SiStripDbParams::SiStripPartitions::const_iterator jter = dbParams_.partitions().end();
187  for ( ; iter != jter; ++iter ) { if ( partition == iter->second.partitionName() ) { break; } }
188  if ( iter == dbParams_.partitions().end() ) {
189  stringstream ss;
190  ss << "[SiStripConfigDb::" << __func__ << "]"
191  << " Partition \"" << partition
192  << "\" not found in partition list, "
193  << " therefore cannot add analysis descriptions!";
194  edm::LogWarning(mlConfigDb_) << ss.str();
195  return;
196  }
197 
198  AnalysisDescriptionsRange range = analyses_.find( partition );
199  if ( range == analyses_.emptyRange() ) {
200 
201  // Make local copy
203  CommissioningAnalysisFactory::vectorCopy( anals, tmp );
204 
205  // Add to local cache
206  analyses_.loadNext( partition, tmp );
207 
208  // Some debug
209  std::stringstream ss;
210  ss << "[SiStripConfigDb::" << __func__ << "]"
211  << " Added " << anals.size()
212  << " analysis descriptions to local cache for partition \""
213  << partition << "\"."
214  << " (Cache holds analysis descriptions for "
215  << analyses_.size() << " partitions.)";
216  LogTrace(mlConfigDb_) << ss.str();
217 
218  } else {
219  stringstream ss;
220  ss << "[SiStripConfigDb::" << __func__ << "]"
221  << " Partition \"" << partition
222  << "\" already found in local cache, "
223  << " therefore cannot add analysis descriptions!";
224  edm::LogWarning(mlConfigDb_) << ss.str();
225  return;
226  }
227 
228 }
229 
230 // -----------------------------------------------------------------------------
231 //
232 void SiStripConfigDb::uploadAnalysisDescriptions( bool calibration_for_physics,
233  std::string partition ) {
234 
235  if ( dbParams_.usingDbCache() ) {
237  << "[SiStripConfigDb::" << __func__ << "]"
238  << " Using database cache! No uploads allowed!";
239  return;
240  }
241 
242  if ( !deviceFactory(__func__) ) { return; }
243 
244  if ( analyses_.empty() ) {
246  << "[SiStripConfigDb::" << __func__ << "]"
247  << " Found no cached analysis descriptions, therefore no upload!";
248  return;
249  }
250 
251  if ( calibration_for_physics && !allowCalibUpload_ ) {
253  << "[SiStripConfigDb::" << __func__ << "]"
254  << " Attempting to upload calibration constants"
255  << " without uploading any hardware descriptions!"
256  << " Aborting upload...";
257  return;
258  } else { allowCalibUpload_ = false; }
259 
260  try {
261 
262  SiStripDbParams::SiStripPartitions::const_iterator iter = dbParams_.partitions().begin();
263  SiStripDbParams::SiStripPartitions::const_iterator jter = dbParams_.partitions().end();
264  for ( ; iter != jter; ++iter ) {
265 
266  if ( partition == "" || partition == iter->second.partitionName() ) {
267 
268  AnalysisDescriptionsRange range = analyses_.find( iter->second.partitionName() );
269  if ( range != analyses_.emptyRange() ) {
270 
271  AnalysisDescriptionsV anals( range.begin(), range.end() );
272 
273  AnalysisType analysis_type = AnalysisDescription::T_UNKNOWN;
274  if ( anals.front() ) { analysis_type = anals.front()->getType(); }
275  if ( analysis_type == AnalysisDescription::T_UNKNOWN ) {
277  << "[SiStripConfigDb::" << __func__ << "]"
278  << " Analysis type is UNKNOWN. Aborting upload!";
279  return;
280  }
281 
282  uint32_t version = deviceFactory(__func__)->uploadAnalysis( iter->second.runNumber(),
283  iter->second.partitionName(),
284  analysis_type,
285  anals,
286  calibration_for_physics );
287 
288  // Update current state with analysis descriptions
289  if ( calibration_for_physics ) { deviceFactory(__func__)->uploadAnalysisState( version ); }
290 
291  // Some debug
292  std::stringstream ss;
293  ss << "[SiStripConfigDb::" << __func__ << "]"
294  << " Uploaded " << anals.size()
295  << " device descriptions to database for partition \""
296  << iter->second.partitionName() << "\".";
297  LogTrace(mlConfigDb_) << ss.str();
298 
299  } else {
300  stringstream ss;
301  ss << "[SiStripConfigDb::" << __func__ << "]"
302  << " Vector of device descriptions is empty for partition \""
303  << iter->second.partitionName()
304  << "\", therefore aborting upload for this partition!";
305  edm::LogWarning(mlConfigDb_) << ss.str();
306  continue;
307  }
308 
309  } else {
310  // stringstream ss;
311  // ss << "[SiStripConfigDb::" << __func__ << "]"
312  // << " Cannot find partition \"" << partition
313  // << "\" in cached partitions list: \""
314  // << dbParams_.partitionNames( dbParams_.partitionNames() )
315  // << "\", therefore aborting upload for this partition!";
316  // edm::LogWarning(mlConfigDb_) << ss.str();
317  }
318 
319  }
320 
321  } catch (...) { handleException( __func__ ); }
322 
323  allowCalibUpload_ = true;
324 
325 }
326 
327 // -----------------------------------------------------------------------------
328 //
329 void SiStripConfigDb::clearAnalysisDescriptions( std::string partition ) {
330  LogTrace(mlConfigDb_) << "[SiStripConfigDb::" << __func__ << "]";
331 
332  if ( analyses_.empty() ) {
333  stringstream ss;
334  ss << "[SiStripConfigDb::" << __func__ << "]"
335  << " Found no cached analysis descriptions!";
336  //edm::LogWarning(mlConfigDb_) << ss.str();
337  return;
338  }
339 
340  // Reproduce temporary cache for "all partitions except specified one" (or clear all if none specified)
341  AnalysisDescriptions temporary_cache;
342  if ( partition == "" ) { temporary_cache = AnalysisDescriptions(); }
343  else {
344  SiStripDbParams::SiStripPartitions::const_iterator iter = dbParams_.partitions().begin();
345  SiStripDbParams::SiStripPartitions::const_iterator jter = dbParams_.partitions().end();
346  for ( ; iter != jter; ++iter ) {
347  if ( partition != iter->second.partitionName() ) {
348  AnalysisDescriptionsRange range = analyses_.find( iter->second.partitionName() );
349  if ( range != analyses_.emptyRange() ) {
350  temporary_cache.loadNext( partition, AnalysisDescriptionsV( range.begin(), range.end() ) );
351  } else {
352  // stringstream ss;
353  // ss << "[SiStripConfigDb::" << __func__ << "]"
354  // << " Cannot find partition \"" << iter->second.partitionName()
355  // << "\" in local cache!";
356  // edm::LogWarning(mlConfigDb_) << ss.str();
357  }
358  }
359  }
360  }
361 
362  // Delete objects in local cache for specified partition (or all if not specified)
363  AnalysisDescriptionsRange anals = analyses_.emptyRange();
364  if ( partition == "" ) {
365  if ( !analyses_.empty() ) {
366  anals = AnalysisDescriptionsRange( analyses_.find( dbParams_.partitions().begin()->second.partitionName() ).begin(),
367  analyses_.find( (--(dbParams_.partitions().end()))->second.partitionName() ).end() );
368  } else { anals = analyses_.emptyRange(); }
369  } else {
370  SiStripDbParams::SiStripPartitions::const_iterator iter = dbParams_.partitions().begin();
371  SiStripDbParams::SiStripPartitions::const_iterator jter = dbParams_.partitions().end();
372  for ( ; iter != jter; ++iter ) { if ( partition == iter->second.partitionName() ) { break; } }
373  anals = analyses_.find( iter->second.partitionName() );
374  }
375 
376  if ( anals != analyses_.emptyRange() ) {
377  AnalysisDescriptionsV::const_iterator ianal = anals.begin();
378  AnalysisDescriptionsV::const_iterator janal = anals.end();
379  for ( ; ianal != janal; ++ianal ) { if ( *ianal ) { delete *ianal; } }
380  } else {
381  stringstream ss;
382  ss << "[SiStripConfigDb::" << __func__ << "]";
383  if ( partition == "" ) { ss << " Found no analysis descriptions in local cache!"; }
384  else { ss << " Found no analysis descriptions in local cache for partition \"" << partition << "\"!"; }
385  edm::LogWarning(mlConfigDb_) << ss.str();
386  }
387 
388  // Overwrite local cache with temporary cache
389  analyses_ = temporary_cache;
390 
391 }
392 
393 // -----------------------------------------------------------------------------
394 //
395 void SiStripConfigDb::printAnalysisDescriptions( std::string partition ) {
396 
397  std::stringstream ss;
398  ss << "[SiStripConfigDb::" << __func__ << "]"
399  << " Contents of AnalysisDescriptions container:" << std::endl;
400  ss << " Number of partitions: " << analyses_.size() << std::endl;
401 
402  // Loop through partitions
403  uint16_t cntr = 0;
404  AnalysisDescriptions::const_iterator ianal = analyses_.begin();
405  AnalysisDescriptions::const_iterator janal = analyses_.end();
406  for ( ; ianal != janal; ++ianal ) {
407 
408  cntr++;
409  if ( partition == "" || partition == ianal->first ) {
410 
411  ss << " Partition number : " << cntr << " (out of " << analyses_.size() << ")" << std::endl;
412  ss << " Partition name : \"" << ianal->first << "\"" << std::endl;
413  ss << " Num of analyses : " << ianal->second.size() << std::endl;
414 
415  // Extract FEC crate, slot, etc
416  std::map< uint32_t, vector<uint32_t> > analyses;
417  AnalysisDescriptionsV::const_iterator iter = ianal->second.begin();
418  AnalysisDescriptionsV::const_iterator jter = ianal->second.end();
419  for ( ; iter != jter; ++iter ) {
420  if ( *iter ) {
421  DeviceAddress addr = deviceAddress( **iter );
422  uint32_t key = SiStripFecKey( addr.fecCrate_,
423  addr.fecSlot_,
424  addr.fecRing_,
425  0,
426  0,
427  0,
428  0 ).key();
429  uint32_t data = SiStripFecKey( addr.fecCrate_,
430  addr.fecSlot_,
431  addr.fecRing_,
432  addr.ccuAddr_,
433  addr.ccuChan_,
434  addr.lldChan_,
435  addr.i2cAddr_ ).key();
436  if ( find( analyses[key].begin(), analyses[key].end(), data ) == analyses[key].end() ) {
437  analyses[key].push_back( data );
438  }
439  }
440  }
441 
442  // Sort contents
443  std::map< uint32_t, std::vector<uint32_t> > tmp;
444  std::map< uint32_t, std::vector<uint32_t> >::const_iterator ii = analyses.begin();
445  std::map< uint32_t, std::vector<uint32_t> >::const_iterator jj = analyses.end();
446  for ( ; ii != jj; ++ii ) {
447  std::vector<uint32_t> temp = ii->second;
448  std::sort( temp.begin(), temp.end() );
449  std::vector<uint32_t>::const_iterator iii = temp.begin();
450  std::vector<uint32_t>::const_iterator jjj = temp.end();
451  for ( ; iii != jjj; ++iii ) { tmp[ii->first].push_back( *iii ); }
452  }
453  analyses.clear();
454  analyses = tmp;
455 
456  // Print FEC crate, slot, etc...
457  std::map< uint32_t, std::vector<uint32_t> >::const_iterator ianal = analyses.begin();
458  std::map< uint32_t, std::vector<uint32_t> >::const_iterator janal = analyses.end();
459  for ( ; ianal != janal; ++ianal ) {
460  SiStripFecKey key(ianal->first);
461  ss << " Found " << std::setw(3) << ianal->second.size()
462  << " analyses for FEC crate/slot/ring "
463  << key.fecCrate() << "/"
464  << key.fecSlot() << "/"
465  << key.fecRing();
466  //<< " (ccu/module/lld/i2c): ";
467  // if ( !ianal->second.empty() ) {
468  // uint16_t first = ianal->second.front();
469  // uint16_t last = ianal->second.front();
470  // std::vector<uint32_t>::const_iterator chan = ianal->second.begin();
471  // for ( ; chan != ianal->second.end(); chan++ ) {
472  // if ( chan != ianal->second.begin() ) {
473  // if ( *chan != last+1 ) {
474  // ss << std::setw(2) << first << "->" << std::setw(2) << last << ", ";
475  // if ( chan != ianal->second.end() ) { first = *(chan+1); }
476  // }
477  // }
478  // last = *chan;
479  // }
480  // if ( first != last ) { ss << std::setw(2) << first << "->" << std::setw(2) << last; }
481  ss << std::endl;
482  }
483 
484  }
485 
486  }
487 
488  LogTrace(mlConfigDb_) << ss.str();
489 
490 }
491 
492 // -----------------------------------------------------------------------------
493 //
495 
496  DeviceAddress addr;
497  try {
498  addr.fecCrate_ = static_cast<uint16_t>( desc.getCrate() + sistrip::FEC_CRATE_OFFSET );
499  addr.fecSlot_ = static_cast<uint16_t>( desc.getSlot() );
500  addr.fecRing_ = static_cast<uint16_t>( desc.getRing() + sistrip::FEC_RING_OFFSET );
501  addr.ccuAddr_ = static_cast<uint16_t>( desc.getCcuAdr() );
502  addr.ccuChan_ = static_cast<uint16_t>( desc.getCcuChan() );
503  addr.lldChan_ = static_cast<uint16_t>( SiStripFecKey::lldChan( desc.getI2cAddr() ) );
504  addr.i2cAddr_ = static_cast<uint16_t>( desc.getI2cAddr() );
505  addr.fedId_ = static_cast<uint16_t>( desc.getFedId() ); //@@ offset required? crate/slot needed?
506  addr.feUnit_ = static_cast<uint16_t>( desc.getFeUnit() );
507  addr.feChan_ = static_cast<uint16_t>( desc.getFeChan() );
508  } catch (...) { handleException( __func__ ); }
509 
510  return addr;
511 }
512 
513 // -----------------------------------------------------------------------------
514 //
515 std::string SiStripConfigDb::analysisType( AnalysisType analysis_type ) const {
516  if ( analysis_type == AnalysisDescription::T_ANALYSIS_FASTFEDCABLING ) { return "FAST_CABLING"; }
517  else if ( analysis_type == AnalysisDescription::T_ANALYSIS_TIMING ) { return "APV_TIMING"; }
518  else if ( analysis_type == AnalysisDescription::T_ANALYSIS_OPTOSCAN ) { return "OPTO_SCAN"; }
519  else if ( analysis_type == AnalysisDescription::T_ANALYSIS_PEDESTALS ) { return "PEDESTALS"; }
520  else if ( analysis_type == AnalysisDescription::T_ANALYSIS_APVLATENCY ) { return "APV_LATENCY"; }
521  else if ( analysis_type == AnalysisDescription::T_ANALYSIS_FINEDELAY ) { return "FINE_DELAY"; }
522  else if ( analysis_type == AnalysisDescription::T_ANALYSIS_CALIBRATION ) { return "CALIBRATION"; }
523  else if ( analysis_type == AnalysisDescription::T_UNKNOWN ) { return "UNKNOWN ANALYSIS TYPE"; }
524  else { return "UNDEFINED ANALYSIS TYPE"; }
525 }
static std::string defaultPartitionName_
const uint16_t & fecRing() const
void loadNext(K const &k, std::vector< T > const &v)
Definition: MapOfVectors.h:97
void uploadAnalysisDescriptions(bool calibration_for_physics=false, std::string partition="")
void addAnalysisDescriptions(std::string partition, AnalysisDescriptionsV &)
static const uint16_t FEC_RING_OFFSET
const uint16_t & lldChan() const
const uint16_t & fecSlot() const
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
const uint32_t & key() const
Definition: SiStripKey.h:126
static const char mlConfigDb_[]
Utility class that identifies a position within the strip tracker control structure, down to the level of an APV25.
Definition: SiStripFecKey.h:46
int np
Definition: AMPTWrapper.h:33
CommissioningAnalysisDescription AnalysisDescription
void clearAnalysisDescriptions(std::string partition="")
#define end
Definition: vmac.h:38
DeviceAddress deviceAddress(const deviceDescription &)
AnalysisDescriptionsRange getAnalysisDescriptions(AnalysisType, std::string partition="")
#define LogTrace(id)
const uint16_t & fecCrate() const
AnalysisDescriptions::range AnalysisDescriptionsRange
CommissioningAnalysisDescription::commissioningType AnalysisType
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
#define begin
Definition: vmac.h:31
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
list key
Definition: combine.py:13
std::string analysisType(AnalysisType) const
std::vector< AnalysisDescription * > AnalysisDescriptionsV
static const uint16_t FEC_CRATE_OFFSET
void printAnalysisDescriptions(std::string partition="")