Belle II Software  release-05-01-25
ARICHUnpackerModule.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2010 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Luka Santelj *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 // Own include
12 #include <arich/modules/arichUnpacker/ARICHUnpackerModule.h>
13 
14 #include <arich/modules/arichUnpacker/ARICHRawDataHeader.h>
15 
16 #include <framework/core/ModuleManager.h>
17 
18 // framework - DataStore
19 #include <framework/datastore/StoreArray.h>
20 #include <framework/datastore/StoreObjPtr.h>
21 
22 // framework aux
23 #include <framework/logging/Logger.h>
24 
25 // Dataobject classes
26 #include <framework/dataobjects/EventMetaData.h>
27 #include <rawdata/dataobjects/RawARICH.h>
28 #include <arich/dataobjects/ARICHDigit.h>
29 #include <arich/dataobjects/ARICHInfo.h>
30 #include <arich/dataobjects/ARICHRawDigit.h>
31 
32 // print bitset
33 #include <bitset>
34 
35 using namespace std;
36 
37 namespace Belle2 {
43  //using namespace ARICH;
44 
45  //-----------------------------------------------------------------
46  // Register module
47  //-----------------------------------------------------------------
48 
49  REG_MODULE(ARICHUnpacker)
50 
51  //-----------------------------------------------------------------
52  // Implementation
53  //-----------------------------------------------------------------
54 
55  ARICHUnpackerModule::ARICHUnpackerModule() : Module(), m_bitMask(0), m_debug(0)
56  {
57  // set module description
58  setDescription("Raw data unpacker for ARICH");
59  setPropertyFlags(c_ParallelProcessingCertified);
60 
61  addParam("bitMask", m_bitMask, "hit bit mask (8 bits/channel, only used for unsuppresed format!)", (uint8_t)0xFF);
62  addParam("debug", m_debug, "prints debug information", 0);
63 
64  addParam("inputRawDataName", m_inputRawDataName, "name of RawARICH store array", string(""));
65  addParam("outputDigitsName", m_outputDigitsName, "name of ARICHDigit store array", string(""));
66  addParam("outputRawDigitsName", m_outputRawDigitsName, "name of ARICHRawDigit store array", string(""));
67  addParam("outputarichinfoName", m_outputarichinfoName, "name of ARICHInfo store array", string(""));
68  addParam("RawUnpackerMode", m_rawmode, "Activate RawUnpacker mode", 0);
69  addParam("DisableUnpackerMode", m_disable_unpacker, "Disable Regular Unpacker mode", 0);
70 
71  }
72 
73  ARICHUnpackerModule::~ARICHUnpackerModule()
74  {
75  }
76 
77  void ARICHUnpackerModule::initialize()
78  {
79 
80  StoreArray<RawARICH> rawData(m_inputRawDataName);
81  rawData.isRequired();
82 
83  StoreArray<ARICHDigit> digits(m_outputDigitsName);
84  digits.registerInDataStore();
85 
86  StoreArray<ARICHRawDigit> rawdigits(m_outputRawDigitsName);
87  rawdigits.registerInDataStore();
88 
89  StoreObjPtr<ARICHInfo> arichinfo(m_outputarichinfoName);
90  arichinfo.registerInDataStore();
91 
92  }
93 
94  void ARICHUnpackerModule::beginRun()
95  {
96  }
97 
98  void ARICHUnpackerModule::event()
99  {
100 
101  StoreArray<RawARICH> rawData(m_inputRawDataName);
102  StoreArray<ARICHDigit> digits(m_outputDigitsName);
103  StoreArray<ARICHRawDigit> rawdigits(m_outputRawDigitsName);
104  StoreObjPtr<ARICHInfo> arichinfo(m_outputarichinfoName);
105  arichinfo.create();
106  StoreObjPtr<EventMetaData> evtMetaData;
107 
108  digits.clear();
109  int trgtype = 16;
110  double vth_thscan = 0.0;
111 
112  if (m_debug) {
113  std::cout << std::endl << "------------------------" << std::endl;
114  std::cout << "Run: " << evtMetaData->getRun() << " Event: " << evtMetaData->getEvent() << std::endl;
115  std::cout << "------------------------" << std::endl << std::endl;
116  }
117 
118  unsigned thscan_mode = 0;
119  // regular Unpacker mode, fill ARICHDigit
120 // if (m_disable_unpacker == 0) {
121 
122  for (auto& raw : rawData) {
123  for (int finesse = 0; finesse < 4; finesse++) {
124  const int* buffer = raw.GetDetectorBuffer(0, finesse);
125  int bufferSize = raw.GetDetectorNwords(0, finesse);
126 
127  if (bufferSize < 1)
128  continue;
129 
130  // record the trigger type from the B2L data
131  trgtype = raw.GetTRGType(0);
132 
133  // read merger header
134  unsigned ibyte = 0;
135  ARICHRawHeader head;
136 
137  readHeader(buffer, ibyte, head);
138 
139  if (m_debug > 1) printBits(buffer, bufferSize);
140 
141  if (m_debug) {
142  std::cout << "Merger header" << std::endl;
143  head.print();
144  }
145  //-- RawDigit for Merger info
146  int type = (int)head.type;
147  int ver = (int)head.version;
148  int boardid = (int)head.mergerID;
149  int febno = (int)head.FEBSlot;
150  unsigned int length_all = (unsigned int)head.length;
151  unsigned int mrg_evtno = (unsigned int)head.trigger;
152  ARICHRawDigit* rawdigit = rawdigits.appendNew(type, ver, boardid, febno, length_all, mrg_evtno);
153  rawdigit->setCopperId(raw.GetNodeID(0));
154  rawdigit->setHslbId(finesse);
155  int nfebs = 0;
156  //-- end of RawDigit for Merger info
157 
158  // record the ibyte here
159  unsigned begin = ibyte;
160 
161  while (ibyte < head.length) {
162 
163  // new feb
164  ARICHRawHeader febHead;
165  readFEHeader(buffer, ibyte, febHead);
166  if (febHead.thscan_mode) {thscan_mode++;}
167  if (m_debug) febHead.print();
168 
169  if (/*febHead.type != head.type ||*/ febHead.version != head.version || febHead.mergerID != head.mergerID
170  || febHead.trigger != head.trigger) B2ERROR("ARICHUnpackerModule: data in header " << LogVar("FEB ID", (unsigned)febHead.FEBSlot) <<
171  " not consistent with data in header " << LogVar("merger ID", (unsigned)head.mergerID));
172 
173  // feb header shift
174  ibyte += ARICHFEB_HEADER_SIZE;
175  int dataLen = febHead.length - ARICHFEB_HEADER_SIZE;
176 
177  febHead.FEBSlot += 1;
178 
179  unsigned mergID = m_mergerMap->getMergerIDfromSN((unsigned)head.mergerID);
180 
181  if (mergID == 99) { B2ERROR("ARICHUnpackerModule: unknown merger number " << LogVar("merger ID", mergID) << LogVar("Serial Number", (unsigned)head.mergerID) << "Merger data will be skipped"); break;}
182 
183  unsigned moduleID = m_mergerMap->getModuleID(mergID, (unsigned)febHead.FEBSlot);
184 
185  if (!moduleID) { B2ERROR("ARICHUnpackerModule: no merger to FEB mapping" << LogVar("merger ID", mergID) << LogVar("Serial Number", (unsigned)head.mergerID) << LogVar("FEB slot", (unsigned)febHead.FEBSlot) << "Merger data will be skipped"); break;}
186 
187  // read data
188  if (m_debug) std::cout << "Hit channels: " << std::endl;
189  if (febHead.type == 1) {
190  for (int i = 0; i < dataLen / 2; i++) {
191  int shift = (3 - ibyte % 4) * 8;
192  uint8_t asicCh = buffer[ibyte / 4] >> shift;
193  ibyte++;
194  shift = (3 - ibyte % 4) * 8;
195  uint8_t hitBitSet = buffer[ibyte / 4] >> shift;
196  if (m_debug && hitBitSet) std::cout << "ch: " << (unsigned)asicCh << " " << std::bitset<8>(hitBitSet) << std::endl;
197  // store digit
198  digits.appendNew(moduleID, (unsigned)asicCh, hitBitSet);
199  ibyte++;
200  }
201  } else if (febHead.type == 2) {
202  unsigned asicCh = 143;
203  for (int i = 0; i < dataLen; i++) {
204  int shift = (3 - ibyte % 4) * 8;
205  uint8_t hitBitSet = buffer[ibyte / 4] >> shift;
206  // store digit if hit
207  if (hitBitSet & m_bitMask) {
208  digits.appendNew(moduleID, asicCh, hitBitSet);
209  }
210  asicCh--;
211  ibyte++;
212  }
213  } else B2ERROR("ARICHUnpackerModule: Unknown data type" << LogVar("type", febHead.type));
214 
215  }
216 
217  if (ceil(ibyte / 4.) != (unsigned)bufferSize)
218  B2WARNING("ARICHUnpackerModule: data buffer size mismatch " << LogVar("size from copper", bufferSize) << LogVar("size from merger",
219  ceil(
220  ibyte / 4.)));
221 
222 
223  //-- If thscan_mode detected from header: proceed to fill ARICHRawDigit
224  //-- If m_rawmode is set to 1: proceed to fill ARICHRawDigit
225  if (thscan_mode == 0 && m_rawmode == 0) continue;
226  //-- go back to beginning again for second loop in case of thscan
227  m_ibyte = begin;
228 
229  while (m_ibyte < length_all) {
230  ARICHRawHeader febHead;
231  readFEHeader(buffer, m_ibyte, febHead);
232  int type_feb = febHead.type;
233  ver = febHead.version;
234  boardid = febHead.mergerID;
235  febno = febHead.FEBSlot;
236 
237  vth_thscan = (febHead.vth * 0.0024) - 1.27;
238  unsigned int length = febHead.length;
239  int evtno = febHead.trigger;
240  unsigned int jbyte = 0;
241  std::stringstream ss;
242  ss << "type=" << type_feb << ", ver=" << ver << " "
243  << ", boardid=" << boardid << ", febno=" << febno
244  << ", length=" << length << ", evtno=" << evtno << " ";
245  bool hasHit = false;
246  long long feb_trigno = 0;
247  for (int i = 0; i < 10; i++) {
248  int val = calbyte(buffer);
249  jbyte++;
250  if (i < 6) {
251  feb_trigno |= (0xff & val) << (5 - i) * 8;
252  }
253  }
255  nfebs++;
256  if (type_feb == 0x02) {//Raw mode
257  int ch = 143;
258  //B2INFO("raw mode");
259  while (jbyte < length) {
260  int val = calbyte(buffer);
261  if (val != 0) {
262  jbyte++;
263  ss << "ch# " << ch << "(" << val << ") ";
264  hasHit = true;
265  if (febno < 0 || febno > 6) {
266  B2ERROR("FEB is bad : " << LogVar("FEB no.", febno) << LogVar("hslb", finesse) << LogVar("type", type_feb) << LogVar("ver",
267  ver) << LogVar("boardid", boardid) << LogVar("febno", febno) << LogVar("length", length) << LogVar("evtno", evtno));
268  }
269  feb.push_back(ch, val);
270  }
271  ch--;
272  if (ch < 0) break;
273  }
274  } else if (type_feb == 0x01) { // Suppressed mode
275  // The below line is commented since it sometimes causes problem during processing threshold scan data.
276  // No harm to comment this line since it is only utilized for threshold scan data.
277  //if (length > 144 * 2 + 10) B2FATAL("error " << LogVar("length", length));
278  //B2INFO("suppreed mode");
279  while (jbyte < length) {
280  int ch = calbyte(buffer);
281  jbyte++;
282  int val = calbyte(buffer);
283  jbyte++;
284  if (val != 0) {
285  ss << "ch# " << ch << "(" << val << ") ";
286  hasHit = true;
287  if (febno < 0 || febno > 6) {
288  B2ERROR("FEB is bad : " << LogVar("FEB no.", febno) << LogVar("hslb", finesse) << LogVar("type", type_feb) << LogVar("ver",
289  ver) << LogVar("boardid", boardid) << LogVar("febno", febno) << LogVar("length", length) << LogVar("evtno", evtno));
290  return;
291  }
292  feb.push_back(ch, val);
293  }
294  }
295  }
296  rawdigit->addFEB(feb, type, ver, boardid, febno, length, evtno, feb_trigno);
297  if (m_debug && hasHit) {
298  B2INFO(ss.str());
299  }
300  }
301 
302 
303 
304  }
305  } // end of rawData loop
306 
307 // } // end of regular unpacker
308  /*
309  // RawUnpacker mode, fill ARICHRawDigit
310  if (m_rawmode == 1) {
311  for (auto& raw : rawData) {
312  for (int finesse = 0; finesse < 4; finesse++) {
313  const int* buf = (const int*)raw.GetDetectorBuffer(0, finesse);
314  int bufSize = raw.GetDetectorNwords(0, finesse);
315  if (bufSize < 1) continue;
316  m_ibyte = 0;
317  // read merger header
318  int type = calbyte(buf);
319  int ver = calbyte(buf);
320  int boardid = calbyte(buf);
321  int febno = calbyte(buf);
322  unsigned int length_all = calword(buf);
323  unsigned int mrg_evtno = calword(buf);
324  ARICHRawDigit* rawdigit = rawdigits.appendNew(type, ver, boardid, febno, length_all, mrg_evtno);
325  rawdigit->setCopperId(raw.GetNodeID(0));
326  rawdigit->setHslbId(finesse);
327  int nfebs = 0;
328  //--done
329  while (m_ibyte < length_all) {
330  int type_feb = calbyte(buf);
331  ver = calbyte(buf);
332  boardid = calbyte(buf);
333  febno = calbyte(buf);
334 
335  // first line: vth value
336  unsigned int vth_int = cal2byte(buf);
337  if (vth_int > 0) { vth_thscan = (vth_int * 0.0024) - 1.27; }
338  // second line: length
339  unsigned int length = cal2byte(buf);
340  int evtno = calword(buf);
341  unsigned int ibyte = 0;
342  std::stringstream ss;
343  ss << "type=" << type_feb << ", ver=" << ver << " "
344  << ", boardid=" << boardid << ", febno=" << febno
345  << ", length=" << length << ", evtno=" << evtno << " ";
346  bool hasHit = false;
347  long long feb_trigno = 0;
348  for (int i = 0; i < 10; i++) {
349  int val = calbyte(buf);
350  ibyte++;
351  if (i < 6) {
352  feb_trigno |= (0xff & val) << (5 - i) * 8;
353  }
354  }
355  ARICHRawDigit::FEBDigit feb;
356  nfebs++;
357  if (type_feb == 0x02) {//Raw mode
358  int ch = 143;
359  //B2INFO("raw mode");
360  while (ibyte < length) {
361  int val = calbyte(buf);
362  if (val != 0) {
363  ibyte++;
364  ss << "ch# " << ch << "(" << val << ") ";
365  hasHit = true;
366  if (febno < 0 || febno > 6) {
367  B2ERROR("FEB is bad : " << LogVar("FEB no.", febno) << LogVar("hslb", finesse) << LogVar("type", type_feb) << LogVar("ver",
368  ver) << LogVar("boardid", boardid) << LogVar("febno", febno) << LogVar("length", length) << LogVar("evtno", evtno));
369  }
370  feb.push_back(ch, val);
371  }
372  ch--;
373  if (ch < 0) break;
374  }
375  } else if (type_feb == 0x01) { // Suppressed mode
376  // The below line is commented since it sometimes causes problem during processing threshold scan data.
377  // No harm to comment this line since it is only utilized for threshold scan data.
378  //if (length > 144 * 2 + 10) B2FATAL("error " << LogVar("length", length));
379  //B2INFO("suppreed mode");
380  while (ibyte < length) {
381  int ch = calbyte(buf);
382  ibyte++;
383  int val = calbyte(buf);
384  ibyte++;
385  if (val != 0) {
386  ss << "ch# " << ch << "(" << val << ") ";
387  hasHit = true;
388  if (febno < 0 || febno > 6) {
389  B2ERROR("FEB is bad : " << LogVar("FEB no.", febno) << LogVar("hslb", finesse) << LogVar("type", type_feb) << LogVar("ver",
390  ver) << LogVar("boardid", boardid) << LogVar("febno", febno) << LogVar("length", length) << LogVar("evtno", evtno));
391  return;
392  }
393  feb.push_back(ch, val);
394  }
395  }
396  }
397  rawdigit->addFEB(feb, type, ver, boardid, febno, length, evtno, feb_trigno);
398  if (m_debug && hasHit) {
399  B2INFO(ss.str());
400  }
401  }
402  }
403  }
404 
405  } // end of raw unpacker
406  */
407  arichinfo->settrgtype(trgtype);
408  if (vth_thscan > -1.27) { arichinfo->setvth_thscan(vth_thscan); }
409  arichinfo->setntrack(0);
410  arichinfo->setnexthit(0);
411  arichinfo->setnhit(0);
412  if (thscan_mode > 0 || m_rawmode != 0)
413  { arichinfo->setthscan_mode(true); }
414  else
415  { arichinfo->setthscan_mode(false); }
416 
417  }
418 
419  void ARICHUnpackerModule::readHeader(const int* buffer, unsigned& ibyte, ARICHRawHeader& head)
420  {
421 
422  // read the first line of header
423  char line1[4];
424  int shift;
425  for (int i = 0; i < 4; i++) {
426  shift = (3 - ibyte % 4) * 8;
427  line1[3 - i] = buffer[ibyte / 4] >> shift;
428  ibyte++;
429  }
430 
431  head.type = line1[3];
432  head.version = line1[2];
433  head.mergerID = line1[1];
434  head.FEBSlot = line1[0];
435 
436  // data length
437  unsigned char len[4];
438  for (int i = 0; i < 4; i++) {
439  shift = (3 - ibyte % 4) * 8;
440  len[3 - i] = buffer[ibyte / 4] >> shift;
441  ibyte++;
442  }
443 
444  unsigned seu = len[2];
445  // This line (16 bits) is actaully not used for data length.
446  len[2] = 0;
447  len[3] = 0;
448  uint32_t* tmp = (uint32_t*)len;
449  head.length = *tmp;
450 
451  for (int i = 0; i < 6; i ++) {
452  head.SEU_FEB[i] = (seu & (1 << i)) != 0;
453  }
454 
455  // trigger number
456  char trg[4];
457  for (int i = 0; i < 4; i++) {
458  shift = (3 - ibyte % 4) * 8;
459  trg[3 - i] = buffer[ibyte / 4] >> shift;
460  ibyte++;
461  }
462  tmp = (uint32_t*)trg;
463  head.trigger = *tmp;
464 
465  }
466 
467  void ARICHUnpackerModule::readFEHeader(const int* buffer, unsigned& ibyte, ARICHRawHeader& head)
468  {
469 
470  // read the first line of header
471  char line1[4];
472  int shift;
473  for (int i = 0; i < 4; i++) {
474  shift = (3 - ibyte % 4) * 8;
475  line1[3 - i] = buffer[ibyte / 4] >> shift;
476  ibyte++;
477  }
478 
479  head.type = line1[3];
480  head.version = line1[2];
481  head.mergerID = line1[1];
482  head.FEBSlot = line1[0];
483 
484  // data length
485  unsigned char len[4];
486  for (int i = 0; i < 4; i++) {
487  shift = (3 - ibyte % 4) * 8;
488  len[3 - i] = buffer[ibyte / 4] >> shift;
489  ibyte++;
490  }
491 
492  unsigned vth_info = len[3] * 256 + len[2];
493  if (vth_info >= 32768) { head.thscan_mode = true; vth_info -= 32768; }
494  head.vth = vth_info;
495  // This line (16 bits) is actaully not used for data length.
496  len[2] = 0;
497  len[3] = 0;
498  uint32_t* tmp = (uint32_t*)len;
499  head.length = *tmp;
500 
501  // trigger number
502  char trg[4];
503  for (int i = 0; i < 4; i++) {
504  shift = (3 - ibyte % 4) * 8;
505  trg[3 - i] = buffer[ibyte / 4] >> shift;
506  ibyte++;
507  }
508  tmp = (uint32_t*)trg;
509  head.trigger = *tmp;
510 
511  }
512 
513  void ARICHUnpackerModule::printBits(const int* buffer, int bufferSize)
514  {
515  for (int i = 0; i < bufferSize; i++) {
516  std::cout << i << "-th word bitset: " << std::bitset<32>(*(buffer + i)) << std::endl;
517  }
518  }
519 
520 
521  void ARICHUnpackerModule::endRun()
522  {
523  }
524 
525  void ARICHUnpackerModule::terminate()
526  {
527  }
528 
529 
531 } // end Belle2 namespace
532 
Belle2::StoreArray::appendNew
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:256
Belle2::ARICHRawDigit
Definition: ARICHRawDigit.h:34
Belle2::ARICHUnpackerModule
Raw data unpacker for ARICH.
Definition: ARICHUnpackerModule.h:42
REG_MODULE
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:652
Belle2::Module
Base class for Modules.
Definition: Module.h:74
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::StoreObjPtr
Type-safe access to single objects in the data store.
Definition: ParticleList.h:33
LogVar
Class to store variables with their name which were sent to the logging service.
Definition: LogVariableStream.h:24
Belle2::StoreArray
Accessor to arrays stored in the data store.
Definition: ECLMatchingPerformanceExpertModule.h:33
Belle2::ARICHRawHeader
Definition: ARICHRawDataHeader.h:17
Belle2::ARICHRawDigit::FEBDigit
Definition: ARICHRawDigit.h:37