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