Belle II Software  release-06-02-00
CDCUnpackerModule.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 #include <cdc/modules/cdcUnpacker/CDCUnpackerModule.h>
10 // DB objects
11 #include <cdc/dbobjects/CDCChannelMap.h>
12 
13 #include <framework/datastore/DataStore.h>
14 #include <framework/logging/Logger.h>
15 #include <framework/utilities/FileSystem.h>
16 // framework - Database
17 #include <framework/database/DBArray.h>
18 
19 #include <iostream>
20 
21 using namespace std;
22 using namespace Belle2;
23 using namespace CDC;
24 
25 //-----------------------------------------------------------------
26 // Register the Module
27 //-----------------------------------------------------------------
28 REG_MODULE(CDCUnpacker)
29 
30 //-----------------------------------------------------------------
31 // Implementation
32 //-----------------------------------------------------------------
33 
35 {
36  //Set module properties
37  setDescription("CDCUnpacker generates CDCHit from Raw data.");
38  setPropertyFlags(c_ParallelProcessingCertified);
39 
40  addParam("rawCDCName", m_rawCDCName, "Name of the RawCDC List name..", string(""));
41  addParam("cdcRawHitWaveFormName", m_cdcRawHitWaveFormName, "Name of the CDCRawHit (Raw data mode).", string(""));
42  addParam("cdcRawHitName", m_cdcRawHitName, "Name of the CDCRawHit (Suppressed mode).", string(""));
43  addParam("cdcHitName", m_cdcHitName, "Name of the CDCHit List name..", string(""));
44  addParam("fadcThreshold", m_fadcThreshold, "Threshold count.", 1);
45 
46  addParam("xmlMapFileName", m_xmlMapFileName, "path+name of the xml file", string(""));
47  addParam("enableStoreCDCRawHit", m_enableStoreCDCRawHit, "Enable to store to the CDCRawHit object", false);
48  addParam("enablePrintOut", m_enablePrintOut, "Enable to print out the data to the terminal", false);
49  addParam("boardIDTrig", m_boardIDTrig, "Board ID for the trigger.", 7);
50  addParam("channelTrig", m_channelTrig, "Channel for the trigger.", 1);
51  addParam("subtractTrigTiming", m_subtractTrigTiming, "Enable to subtract the trigger timing from TDCs.", false);
52  addParam("tdcOffset", m_tdcOffset, "TDC offset (in TDC count).", 0);
53  addParam("enableDatabase", m_enableDatabase, "Enable database to read the channel map.", true);
54  addParam("enable2ndHit", m_enable2ndHit, "Enable 2nd hit timing as a individual CDCHit object.", false);
55  addParam("tdcAuxOffset", m_tdcAuxOffset, "TDC auxiliary offset (in TDC count).", 0);
56  addParam("pedestalSubtraction", m_pedestalSubtraction, "Enbale ADC pedestal subtraction.", m_pedestalSubtraction);
57 
58 }
59 
60 CDCUnpackerModule::~CDCUnpackerModule()
61 {
62 }
63 
64 void CDCUnpackerModule::initialize()
65 {
66  m_dataLengthError = false;
67  m_dataSizeError = false;
68  m_channelMapFromDB = new DBArray<CDCChannelMap>;
69  if ((*m_channelMapFromDB).isValid()) {
70  // B2INFO("Channel map is valid");
71  } else {
72  B2FATAL("Channel map is not valid");
73  }
74 
75  if (m_enablePrintOut == true) {
76  B2INFO("CDCUnpacker: initialize() Called.");
77  }
78 
79  m_rawCDCs.isRequired(m_rawCDCName);
80  m_CDCRawHitWaveForms.registerInDataStore(m_cdcRawHitWaveFormName);
81  m_CDCRawHits.registerInDataStore(m_cdcRawHitName);
82  m_CDCHits.registerInDataStore(m_cdcHitName);
83 
84  if (m_enablePrintOut == true) {
85  B2INFO("CDCUnpacker: " << LogVar("FADC threshold", m_fadcThreshold));
86  }
87 }
88 
89 void CDCUnpackerModule::beginRun()
90 {
91  if (m_enablePrintOut == true) {
92  B2INFO("CDCUnpacker: beginRun() called.");
93  }
94 
95 
96  loadMap();
97  setADCPedestal();
98 }
99 
100 void CDCUnpackerModule::event()
101 {
102  if (m_enablePrintOut == true) {
103  B2INFO("CDCUnpacker: event() started.");
104  }
105 
106  // TDC count for the trigger scinti.
107  int tdcCountTrig = m_tdcOffset;
108 
109  // Create Data objects.
110  m_CDCHits.clear();
111 
112  if (m_enableStoreCDCRawHit == true) {
113  m_CDCRawHits.clear();
114  m_CDCRawHitWaveForms.clear();
115  }
116 
117  //
118  // Proccess RawCDC data block.
119  //
120 
121  const int nEntries = m_rawCDCs.getEntries();
122 
123  B2DEBUG(99, "nEntries of RawCDCs : " << nEntries);
124  for (int i = 0; i < nEntries; ++i) {
125  const int subDetectorId = m_rawCDCs[i]->GetNodeID(0);
126  const int iNode = (subDetectorId & 0xFFFFFF);
127  const int nEntriesRawCDC = m_rawCDCs[i]->GetNumEntries();
128 
129  B2DEBUG(99, LogVar("nEntries of rawCDC[i]", nEntriesRawCDC));
130  for (int j = 0; j < nEntriesRawCDC; ++j) {
131  int trigType = m_rawCDCs[i]->GetTRGType(j); // Get event type of L1 trigger.
132  int nWords[48];
133  int* data32tab[48];
134  int MaxNumOfCh = m_rawCDCs[i]->GetMaxNumOfCh(j);
135  string readoutName;
136  if (MaxNumOfCh == 4) readoutName = "COPPER";
137  else if (MaxNumOfCh == 48) readoutName = "PCIe40";
138  else
139  B2FATAL("CDC UnpackerModule: Invalid value of GetMaxNumOfCh from raw data: " << LogVar("Number of ch: ",
140  m_rawCDCs[i]->GetMaxNumOfCh(j)));
141 
142  for (int k = 0; k < MaxNumOfCh; ++k) {
143  nWords[k] = m_rawCDCs[i]->GetDetectorNwords(j, k);
144  data32tab[k] = (int*)m_rawCDCs[i]->GetDetectorBuffer(j, k);
145  }
146 
147  //
148  // Search Data from Finess 0->MaxNumOfCh (4/48 for COPPER/PCIe40).
149  //
150 
151  for (int iFiness = 0; iFiness < MaxNumOfCh; ++iFiness) {
152  int* ibuf = data32tab[iFiness];
153  const int nWord = nWords[iFiness];
154  B2DEBUG(99, LogVar("nWords (from " + readoutName + " header)", nWord));
155 
156  if (m_enablePrintOut == true) {
157  B2INFO("CDCUnpacker : Print out CDC data block.");
158  printBuffer(ibuf, nWord);
159  }
160 
161  const int c_headearWords = 3;
162  if (nWord < c_headearWords) {
163  if (m_enablePrintOut == true) {
164  B2WARNING("CDCUnpacker : No CDC block header.");
165  }
166  continue;
167  }
168 
169  if (m_enablePrintOut == true) {
170  B2INFO("CDCUnpacker : RawDataBlock(CDC) : Block # "
171  << LogVar("Block", i)
172  << LogVar("Node", iNode)
173  << LogVar("Finness", iFiness));
174  }
175 
176  setCDCPacketHeader(ibuf);
177 
178  const int dataType = getDataType();
179  const int dataLength = getDataLength() / 4; // Data length in int word (4bytes).
180  const int swDataLength = dataLength * 2; // Data length in short word (2bytes).
181 
182 
183  if (dataLength != (nWord - c_headearWords)) {
184  if (m_dataSizeError == false) {
185  B2ERROR("Inconsistent data size between " + readoutName + " and CDC FEE."
186  << LogVar("data length", dataLength) << LogVar("nWord", nWord)
187  << LogVar("Node ID", iNode) << LogVar("Finness ID", iFiness));
188  m_dataSizeError = true;
189  } else {
190  B2WARNING("Inconsistent data size between " + readoutName + " and CDC FEE."
191  << LogVar("data length", dataLength) << LogVar("nWord", nWord)
192  << LogVar("Node ID", iNode) << LogVar("Finness ID", iFiness));
193  }
194  continue;
195  }
196  if (m_enablePrintOut == true) {
197  B2INFO("CDCUnpacker : " << LogVar("Data size", dataLength));
198  }
199 
200  const int board = getBoardId();
201  const int trgNumber = getTriggerNumber();
202  const int trgTime = getTriggerTime();
203 
204  if (m_enablePrintOut == true) {
205  B2INFO("CDCUnpacker : " << LogVar("Board", board) << LogVar("Trigger number", trgNumber)
206  << LogVar("Trigger time ", trgTime));
207  }
208 
209  //
210  // Check the data type (raw or supressed mode?).
211  //
212 
213  if (dataType == 1) { // Raw data mode.
214  if (m_enablePrintOut == true) {
215  B2INFO("CDCUnpacker : Raw data mode.");
216  }
217 
218  m_buffer.clear();
219 
220  for (int it = 0; it < dataLength; ++it) {
221  int index = it + c_headearWords;
222 
223  m_buffer.push_back(static_cast<unsigned short>((ibuf[index] & 0xffff0000) >> 16));
224  m_buffer.push_back(static_cast<unsigned short>(ibuf[index] & 0xffff));
225  }
226 
227  const int fadcTdcChannels = 48; // Total channels of FADC or TDC.
228  const int nSamples = swDataLength / (2 * fadcTdcChannels); // Number of samplings.
229 
230  std::vector<unsigned short> fadcs;
231  std::vector<unsigned short> tdcs;
232 
233  for (int iCh = 0; iCh < fadcTdcChannels; ++iCh) {
234  const int offset = fadcTdcChannels;
235  unsigned short fadcSum = 0; // FADC sum below thereshold.
236  unsigned short tdc1 = 0x7fff; // Fastest TDC.
237  unsigned short tdc2 = 0x7fff; // 2nd fastest TDC.
238 
239  for (int iSample = 0; iSample < nSamples; ++iSample) {
240  // FADC value for each sample and channel.
241 
242  unsigned short fadc = m_buffer.at(iCh + 2 * fadcTdcChannels * iSample);
243 
244  if (fadc > m_fadcThreshold) {
245  fadcSum += fadc;
246  }
247  // TDC count for each sample and channel.
248 
249  unsigned short tdc = m_buffer.at(iCh + 2 * fadcTdcChannels * iSample + offset) & 0x7fff;
250  unsigned short tdcIsValid = (m_buffer.at(iCh + 2 * fadcTdcChannels * iSample + offset) & 0x8000) >> 15;
251  if (tdcIsValid == 1) { // good tdc data.
252  if (tdc > 0) { // if hit timng is 0, skip.
253  if (tdc < tdc1) {
254  tdc2 = tdc1; // 2nd fastest hit
255  tdc1 = tdc; // fastest hit.
256  }
257  }
258  }
259 
260  fadcs.push_back(fadc);
261  tdcs.push_back(tdc);
262  if (m_enableStoreCDCRawHit == true) {
263  // Store to the CDCRawHitWaveForm object.
264  const unsigned short status = 0;
265  m_CDCRawHitWaveForms.appendNew(status, trgNumber, iNode, iFiness, board, iCh, iSample, trgTime, fadc, tdc);
266  }
267 
268  }
269 
270  if (tdc1 != 0x7fff) {
271  // Store to the CDCHit object.
272  const WireID wireId = getWireID(board, iCh);
273 
274  if (trgTime < tdc1) {
275  tdc1 = (trgTime | 0x8000) - tdc1;
276  } else {
277  tdc1 = trgTime - tdc1;
278  }
279  CDCHit* firstHit = m_CDCHits.appendNew(tdc1, fadcSum, wireId);
280  if (m_enable2ndHit == true) {
281  CDCHit* secondHit = m_CDCHits.appendNew(tdc2, fadcSum, wireId);
282  secondHit->setOtherHitIndices(firstHit);
283  secondHit->set2ndHitFlag();
284  }
285  }
286 
287 
288 
289 
290  if (m_enablePrintOut == true) {
291  //
292  // Print out (for debug).
293  //
294 
295  printf("FADC ch %2d : ", iCh);
296  for (int iSample = 0; iSample < nSamples; ++iSample) {
297  printf("%4x ", fadcs.at(iSample));
298  }
299  printf("\n");
300 
301  printf("TDC ch %2d : ", iCh);
302  for (int iSample = 0; iSample < nSamples; ++iSample) {
303  printf("%4x ", tdcs.at(iSample));
304  }
305  printf("\n");
306  }
307 
308  }
309 
310  } else if (dataType == 2) { // Suppressed mode.
311  if (m_enablePrintOut == true) {
312  B2INFO("CDCUnpacker : Suppressed mode.");
313  }
314 
315  // convert int array -> short array.
316  m_buffer.clear();
317  for (int it = 0; it < dataLength; ++it) {
318  int index = it + c_headearWords;
319  m_buffer.push_back(static_cast<unsigned short>((ibuf[index] & 0xffff0000) >> 16));
320  m_buffer.push_back(static_cast<unsigned short>(ibuf[index] & 0xffff));
321  }
322 
323  const int bufSize = static_cast<int>(m_buffer.size());
324  for (int it = 0; it < bufSize;) {
325  unsigned short header = m_buffer.at(it); // Header.
326  unsigned short ch = (header & 0xff00) >> 8; // Channel ID in FE.
327  unsigned short length = (header & 0xff) / 2; // Data length in short word.
328 
329  if (header == 0xff02) {
330  it++;
331  continue;
332  }
333 
334  if (!((length == 4) || (length == 5))) {
335  if (m_dataLengthError == false) {
336  B2ERROR("CDCUnpacker : data length should be 4 or 5 words."
337  << LogVar("data length", length)
338  << LogVar("board id", board)
339  << LogVar("channel", ch));
340  m_dataLengthError = true;
341  } else {
342  B2WARNING("CDCUnpacker : data length should be 4 or 5 words."
343  << LogVar("data length", length)
344  << LogVar("board id", board)
345  << LogVar("channel", ch));
346  }
347  it += length;
348  break;
349  }
350 
351  unsigned short tot = m_buffer.at(it + 1); // Time over threshold.
352  unsigned short fadcSum = m_buffer.at(it + 2); // FADC sum.
353  if (m_pedestalSubtraction == true) {
354  int diff = fadcSum - (*m_adcPedestalFromDB)->getPedestal(board, ch);
355  if (diff <= m_fadcThreshold) {
356  fadcSum = 0;
357  } else {
358  fadcSum = static_cast<unsigned short>(diff);
359  }
360  }
361  unsigned short tdc1 = 0; // TDC count.
362  unsigned short tdc2 = 0; // 2nd TDC count.
363  unsigned short tdcFlag = 0; // Multiple hit or not (1 for multi hits, 0 for single hit).
364 
365  if (length == 4) {
366  tdc1 = m_buffer.at(it + 3);
367  } else if (length == 5) {
368  tdc1 = m_buffer.at(it + 3);
369  tdc2 = m_buffer.at(it + 4) & 0x7fff;
370  tdcFlag = (m_buffer.at(it + 4) & 0x8000) >> 15;
371  } else {
372  B2ERROR("CDCUnpacker : Undefined data length (should be 4 or 5 short words) ");
373  }
374 
375  if (m_enablePrintOut == true) {
376  printf("%4x %4x %4x %4x %4x %4x %4x \n", ch, length, tot, fadcSum, tdc1, tdc2, tdcFlag);
377  }
378  if (length == 4 || length == 5) {
379 
380  // const unsigned short status = 0;
381  const unsigned short status = trigType; // temporally trigger type is stored, here.
382  // Store to the CDCHit.
383  const WireID wireId = getWireID(board, ch);
384 
385  if (isValidBoardChannel(wireId)) {
386  if (board == m_boardIDTrig && ch == m_channelTrig) {
387  tdcCountTrig = tdc1;
388  } else {
389  CDCHit* firstHit = m_CDCHits.appendNew(tdc1, fadcSum, wireId,
390  0, tot);
391  if (length == 5) {
392  if (m_enable2ndHit == true) {
393  CDCHit* secondHit = m_CDCHits.appendNew(tdc2, fadcSum, wireId,
394  0, tot);
395  secondHit->setOtherHitIndices(firstHit);
396  secondHit->set2ndHitFlag();
397  }
398  }
399  }
400 
401  if (m_enableStoreCDCRawHit == true) {
402  // Store to the CDCRawHit object.
403  m_CDCRawHits.appendNew(status, trgNumber, iNode, iFiness, board, ch,
404  trgTime, fadcSum, tdc1, tdc2, tot);
405  }
406 
407  } else {
408  B2WARNING("Undefined board id is fired: " << LogVar("board id", board) << " " << LogVar("channel", ch));
409  }
410  }
411  it += static_cast<int>(length);
412  }
413 
414  } else {
415  B2WARNING("CDCUnpacker : Undefined CDC Data Block : Block # " << LogVar("block id", i));
416  }
417  }
418  }
419  }
420 
421  //
422  // t0 correction w.r.t. the timing of the trigger counter.
423  //
424  if (m_subtractTrigTiming == true) {
425  for (auto& hit : m_CDCHits) {
426  int tdc = hit.getTDCCount();
427  if (hit.is2ndHit()) {
428  if (tdc != 0) {
429  tdc = tdc - (tdcCountTrig - m_tdcOffset);
430  }
431  } else {
432  tdc = tdc - (tdcCountTrig - m_tdcOffset);
433  }
434 
435  tdc -= m_tdcAuxOffset;
436  hit.setTDCCount(static_cast<unsigned short>(tdc));
437  }
438  }
439 }
440 
441 void CDCUnpackerModule::endRun()
442 {
443  if (m_enablePrintOut == true) {
444  B2INFO("CDCUnpacker : End run.");
445  }
446 }
447 
448 void CDCUnpackerModule::terminate()
449 {
450  if (m_enablePrintOut == true) {
451  B2INFO("CDCUnpacker : Terminated.");
452  }
453 
454  if (m_channelMapFromDB) delete m_channelMapFromDB;
455  if (m_adcPedestalFromDB) delete m_adcPedestalFromDB;
456 }
457 
458 
459 WireID CDCUnpackerModule::getWireID(int iBoard, int iCh) const
460 {
461  return m_map[iBoard][iCh];
462 }
463 
464 void CDCUnpackerModule::loadMap()
465 {
466 
467  if (m_enableDatabase == false) {
468 
469  // Read the channel map from the local text.
470  std::string fileName = FileSystem::findFile(m_xmlMapFileName);
471  std::cout << fileName << std::endl;
472  if (fileName == "") {
473  B2ERROR("CDC unpacker can't find a filename: " << LogVar("file name", fileName));
474  exit(1);
475  }
476 
477 
478  ifstream ifs;
479  ifs.open(fileName.c_str());
480  int isl;
481  int icl;
482  int iw;
483  int iBoard;
484  int iCh;
485 
486  while (!ifs.eof()) {
487  ifs >> isl >> icl >> iw >> iBoard >> iCh;
488  const WireID wireId(isl, icl, iw);
489  m_map[iBoard][iCh] = wireId;
490  }
491  } else {
492  for (const auto& cm : (*m_channelMapFromDB)) {
493  const int isl = cm.getISuperLayer();
494  const int il = cm.getILayer();
495  const int iw = cm.getIWire();
496  const int iBoard = cm.getBoardID();
497  const int iCh = cm.getBoardChannel();
498  const WireID wireId(isl, il, iw);
499  m_map[iBoard][iCh] = wireId;
500  }
501  }
502 }
503 
504 void CDCUnpackerModule::setADCPedestal()
505 {
506  if (m_pedestalSubtraction == true) {
507  m_adcPedestalFromDB = new DBObjPtr<CDCADCDeltaPedestals>;
508  if (!(*m_adcPedestalFromDB).isValid()) {
509  m_pedestalSubtraction = false;
510  }
511  }
512 
513 }
514 
515 void CDCUnpackerModule::printBuffer(int* buf, int nwords)
516 {
517 
518  for (int j = 0; j < nwords; ++j) {
519  printf(" %.8x", buf[j]);
520  if ((j + 1) % 10 == 0) {
521  printf("\n");
522  }
523  }
524  printf("\n");
525 
526  return;
527 }
Class containing the result of the unpacker in raw data and the result of the digitizer in simulation...
Definition: CDCHit.h:40
void set2ndHitFlag()
Setter for 2nd hit flag.
Definition: CDCHit.h:113
void setOtherHitIndices(CDCHit *otherHit)
Setter for the other hit indices.
Definition: CDCHit.h:147
CDCUnpackerModule: The CDC Raw Hits Decoder.
Class for accessing arrays of objects in the database.
Definition: DBArray.h:26
Class for accessing objects in the database.
Definition: DBObjPtr.h:21
Base class for Modules.
Definition: Module.h:72
Class to identify a wire inside the CDC.
Definition: WireID.h:34
unsigned short getISuperLayer() const
Getter for Super-Layer.
Definition: WireID.h:130
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.