Belle II Software  release-06-00-14
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[4];
133  nWords[0] = m_rawCDCs[i]->Get1stDetectorNwords(j);
134  nWords[1] = m_rawCDCs[i]->Get2ndDetectorNwords(j);
135  nWords[2] = m_rawCDCs[i]->Get3rdDetectorNwords(j);
136  nWords[3] = m_rawCDCs[i]->Get4thDetectorNwords(j);
137 
138  int* data32tab[4];
139  data32tab[0] = (int*)m_rawCDCs[i]->Get1stDetectorBuffer(j);
140  data32tab[1] = (int*)m_rawCDCs[i]->Get2ndDetectorBuffer(j);
141  data32tab[2] = (int*)m_rawCDCs[i]->Get3rdDetectorBuffer(j);
142  data32tab[3] = (int*)m_rawCDCs[i]->Get4thDetectorBuffer(j);
143 
144 
145 
146  //
147  // Search Data from Finess A to D (0->3).
148  //
149 
150  for (int iFiness = 0; iFiness < 4; ++iFiness) {
151  int* ibuf = data32tab[iFiness];
152  const int nWord = nWords[iFiness];
153  B2DEBUG(99, LogVar("nWords (from COPPER header)", nWord));
154 
155  if (m_enablePrintOut == true) {
156  B2INFO("CDCUnpacker : Print out CDC data block.");
157  printBuffer(ibuf, nWord);
158  }
159 
160  const int c_headearWords = 3;
161  if (nWord < c_headearWords) {
162  if (m_enablePrintOut == true) {
163  B2WARNING("CDCUnpacker : No CDC block header.");
164  }
165  continue;
166  }
167 
168  if (m_enablePrintOut == true) {
169  B2INFO("CDCUnpacker : RawDataBlock(CDC) : Block # "
170  << LogVar("Block", i)
171  << LogVar("Node", iNode)
172  << LogVar("Finness", iFiness));
173  }
174 
175  setCDCPacketHeader(ibuf);
176 
177  const int dataType = getDataType();
178  const int dataLength = getDataLength() / 4; // Data length in int word (4bytes).
179  const int swDataLength = dataLength * 2; // Data length in short word (2bytes).
180 
181 
182  if (dataLength != (nWord - c_headearWords)) {
183  if (m_dataSizeError == false) {
184  B2ERROR("Inconsistent data size between COPPER and CDC FEE."
185  << LogVar("data length", dataLength) << LogVar("nWord", nWord)
186  << LogVar("Node ID", iNode) << LogVar("Finness ID", iFiness));
187  m_dataSizeError = true;
188  } else {
189  B2WARNING("Inconsistent data size between COPPER and CDC FEE."
190  << LogVar("data length", dataLength) << LogVar("nWord", nWord)
191  << LogVar("Node ID", iNode) << LogVar("Finness ID", iFiness));
192  }
193  continue;
194  }
195  if (m_enablePrintOut == true) {
196  B2INFO("CDCUnpacker : " << LogVar("Data size", dataLength));
197  }
198 
199  const int board = getBoardId();
200  const int trgNumber = getTriggerNumber();
201  const int trgTime = getTriggerTime();
202 
203  if (m_enablePrintOut == true) {
204  B2INFO("CDCUnpacker : " << LogVar("Board", board) << LogVar("Trigger number", trgNumber)
205  << LogVar("Trigger time ", trgTime));
206  }
207 
208  //
209  // Check the data type (raw or supressed mode?).
210  //
211 
212  if (dataType == 1) { // Raw data mode.
213  if (m_enablePrintOut == true) {
214  B2INFO("CDCUnpacker : Raw data mode.");
215  }
216 
217  m_buffer.clear();
218 
219  for (int it = 0; it < dataLength; ++it) {
220  int index = it + c_headearWords;
221 
222  m_buffer.push_back(static_cast<unsigned short>((ibuf[index] & 0xffff0000) >> 16));
223  m_buffer.push_back(static_cast<unsigned short>(ibuf[index] & 0xffff));
224  }
225 
226  const int fadcTdcChannels = 48; // Total channels of FADC or TDC.
227  const int nSamples = swDataLength / (2 * fadcTdcChannels); // Number of samplings.
228 
229  std::vector<unsigned short> fadcs;
230  std::vector<unsigned short> tdcs;
231 
232  for (int iCh = 0; iCh < fadcTdcChannels; ++iCh) {
233  const int offset = fadcTdcChannels;
234  unsigned short fadcSum = 0; // FADC sum below thereshold.
235  unsigned short tdc1 = 0x7fff; // Fastest TDC.
236  unsigned short tdc2 = 0x7fff; // 2nd fastest TDC.
237 
238  for (int iSample = 0; iSample < nSamples; ++iSample) {
239  // FADC value for each sample and channel.
240 
241  unsigned short fadc = m_buffer.at(iCh + 2 * fadcTdcChannels * iSample);
242 
243  if (fadc > m_fadcThreshold) {
244  fadcSum += fadc;
245  }
246  // TDC count for each sample and channel.
247 
248  unsigned short tdc = m_buffer.at(iCh + 2 * fadcTdcChannels * iSample + offset) & 0x7fff;
249  unsigned short tdcIsValid = (m_buffer.at(iCh + 2 * fadcTdcChannels * iSample + offset) & 0x8000) >> 15;
250  if (tdcIsValid == 1) { // good tdc data.
251  if (tdc > 0) { // if hit timng is 0, skip.
252  if (tdc < tdc1) {
253  tdc2 = tdc1; // 2nd fastest hit
254  tdc1 = tdc; // fastest hit.
255  }
256  }
257  }
258 
259  fadcs.push_back(fadc);
260  tdcs.push_back(tdc);
261  if (m_enableStoreCDCRawHit == true) {
262  // Store to the CDCRawHitWaveForm object.
263  const unsigned short status = 0;
264  m_CDCRawHitWaveForms.appendNew(status, trgNumber, iNode, iFiness, board, iCh, iSample, trgTime, fadc, tdc);
265  }
266 
267  }
268 
269  if (tdc1 != 0x7fff) {
270  // Store to the CDCHit object.
271  const WireID wireId = getWireID(board, iCh);
272 
273  if (trgTime < tdc1) {
274  tdc1 = (trgTime | 0x8000) - tdc1;
275  } else {
276  tdc1 = trgTime - tdc1;
277  }
278  CDCHit* firstHit = m_CDCHits.appendNew(tdc1, fadcSum, wireId);
279  if (m_enable2ndHit == true) {
280  CDCHit* secondHit = m_CDCHits.appendNew(tdc2, fadcSum, wireId);
281  secondHit->setOtherHitIndices(firstHit);
282  secondHit->set2ndHitFlag();
283  }
284  }
285 
286 
287 
288 
289  if (m_enablePrintOut == true) {
290  //
291  // Print out (for debug).
292  //
293 
294  printf("FADC ch %2d : ", iCh);
295  for (int iSample = 0; iSample < nSamples; ++iSample) {
296  printf("%4x ", fadcs.at(iSample));
297  }
298  printf("\n");
299 
300  printf("TDC ch %2d : ", iCh);
301  for (int iSample = 0; iSample < nSamples; ++iSample) {
302  printf("%4x ", tdcs.at(iSample));
303  }
304  printf("\n");
305  }
306 
307  }
308 
309  } else if (dataType == 2) { // Suppressed mode.
310  if (m_enablePrintOut == true) {
311  B2INFO("CDCUnpacker : Suppressed mode.");
312  }
313 
314  // convert int array -> short array.
315  m_buffer.clear();
316  for (int it = 0; it < dataLength; ++it) {
317  int index = it + c_headearWords;
318  m_buffer.push_back(static_cast<unsigned short>((ibuf[index] & 0xffff0000) >> 16));
319  m_buffer.push_back(static_cast<unsigned short>(ibuf[index] & 0xffff));
320  }
321 
322  const int bufSize = static_cast<int>(m_buffer.size());
323  for (int it = 0; it < bufSize;) {
324  unsigned short header = m_buffer.at(it); // Header.
325  unsigned short ch = (header & 0xff00) >> 8; // Channel ID in FE.
326  unsigned short length = (header & 0xff) / 2; // Data length in short word.
327 
328  if (header == 0xff02) {
329  it++;
330  continue;
331  }
332 
333  if (!((length == 4) || (length == 5))) {
334  if (m_dataLengthError == false) {
335  B2ERROR("CDCUnpacker : data length should be 4 or 5 words."
336  << LogVar("data length", length)
337  << LogVar("board id", board)
338  << LogVar("channel", ch));
339  m_dataLengthError = true;
340  } else {
341  B2WARNING("CDCUnpacker : data length should be 4 or 5 words."
342  << LogVar("data length", length)
343  << LogVar("board id", board)
344  << LogVar("channel", ch));
345  }
346  it += length;
347  break;
348  }
349 
350  unsigned short tot = m_buffer.at(it + 1); // Time over threshold.
351  unsigned short fadcSum = m_buffer.at(it + 2); // FADC sum.
352  if (m_pedestalSubtraction == true) {
353  int diff = fadcSum - (*m_adcPedestalFromDB)->getPedestal(board, ch);
354  if (diff <= m_fadcThreshold) {
355  fadcSum = 0;
356  } else {
357  fadcSum = static_cast<unsigned short>(diff);
358  }
359  }
360  unsigned short tdc1 = 0; // TDC count.
361  unsigned short tdc2 = 0; // 2nd TDC count.
362  unsigned short tdcFlag = 0; // Multiple hit or not (1 for multi hits, 0 for single hit).
363 
364  if (length == 4) {
365  tdc1 = m_buffer.at(it + 3);
366  } else if (length == 5) {
367  tdc1 = m_buffer.at(it + 3);
368  tdc2 = m_buffer.at(it + 4) & 0x7fff;
369  tdcFlag = (m_buffer.at(it + 4) & 0x8000) >> 15;
370  } else {
371  B2ERROR("CDCUnpacker : Undefined data length (should be 4 or 5 short words) ");
372  }
373 
374  if (m_enablePrintOut == true) {
375  printf("%4x %4x %4x %4x %4x %4x %4x \n", ch, length, tot, fadcSum, tdc1, tdc2, tdcFlag);
376  }
377  if (length == 4 || length == 5) {
378 
379  // const unsigned short status = 0;
380  const unsigned short status = trigType; // temporally trigger type is stored, here.
381  // Store to the CDCHit.
382  const WireID wireId = getWireID(board, ch);
383 
384  if (isValidBoardChannel(wireId)) {
385  if (board == m_boardIDTrig && ch == m_channelTrig) {
386  tdcCountTrig = tdc1;
387  } else {
388  CDCHit* firstHit = m_CDCHits.appendNew(tdc1, fadcSum, wireId,
389  0, tot);
390  if (length == 5) {
391  if (m_enable2ndHit == true) {
392  CDCHit* secondHit = m_CDCHits.appendNew(tdc2, fadcSum, wireId,
393  0, tot);
394  secondHit->setOtherHitIndices(firstHit);
395  secondHit->set2ndHitFlag();
396  }
397  }
398  }
399 
400  if (m_enableStoreCDCRawHit == true) {
401  // Store to the CDCRawHit object.
402  m_CDCRawHits.appendNew(status, trgNumber, iNode, iFiness, board, ch,
403  trgTime, fadcSum, tdc1, tdc2, tot);
404  }
405 
406  } else {
407  B2WARNING("Undefined board id is fired: " << LogVar("board id", board) << " " << LogVar("channel", ch));
408  }
409  }
410  it += static_cast<int>(length);
411  }
412 
413  } else {
414  B2WARNING("CDCUnpacker : Undefined CDC Data Block : Block # " << LogVar("block id", i));
415  }
416  }
417  }
418  }
419 
420  //
421  // t0 correction w.r.t. the timing of the trigger counter.
422  //
423  if (m_subtractTrigTiming == true) {
424  for (auto& hit : m_CDCHits) {
425  int tdc = hit.getTDCCount();
426  if (hit.is2ndHit()) {
427  if (tdc != 0) {
428  tdc = tdc - (tdcCountTrig - m_tdcOffset);
429  }
430  } else {
431  tdc = tdc - (tdcCountTrig - m_tdcOffset);
432  }
433 
434  tdc -= m_tdcAuxOffset;
435  hit.setTDCCount(static_cast<unsigned short>(tdc));
436  }
437  }
438 }
439 
440 void CDCUnpackerModule::endRun()
441 {
442  if (m_enablePrintOut == true) {
443  B2INFO("CDCUnpacker : End run.");
444  }
445 }
446 
447 void CDCUnpackerModule::terminate()
448 {
449  if (m_enablePrintOut == true) {
450  B2INFO("CDCUnpacker : Terminated.");
451  }
452 
453  if (m_channelMapFromDB) delete m_channelMapFromDB;
454  if (m_adcPedestalFromDB) delete m_adcPedestalFromDB;
455 }
456 
457 
458 WireID CDCUnpackerModule::getWireID(int iBoard, int iCh) const
459 {
460  return m_map[iBoard][iCh];
461 }
462 
463 void CDCUnpackerModule::loadMap()
464 {
465 
466  if (m_enableDatabase == false) {
467 
468  // Read the channel map from the local text.
469  std::string fileName = FileSystem::findFile(m_xmlMapFileName);
470  std::cout << fileName << std::endl;
471  if (fileName == "") {
472  B2ERROR("CDC unpacker can't find a filename: " << LogVar("file name", fileName));
473  exit(1);
474  }
475 
476 
477  ifstream ifs;
478  ifs.open(fileName.c_str());
479  int isl;
480  int icl;
481  int iw;
482  int iBoard;
483  int iCh;
484 
485  while (!ifs.eof()) {
486  ifs >> isl >> icl >> iw >> iBoard >> iCh;
487  const WireID wireId(isl, icl, iw);
488  m_map[iBoard][iCh] = wireId;
489  }
490  } else {
491  for (const auto& cm : (*m_channelMapFromDB)) {
492  const int isl = cm.getISuperLayer();
493  const int il = cm.getILayer();
494  const int iw = cm.getIWire();
495  const int iBoard = cm.getBoardID();
496  const int iCh = cm.getBoardChannel();
497  const WireID wireId(isl, il, iw);
498  m_map[iBoard][iCh] = wireId;
499  }
500  }
501 }
502 
503 void CDCUnpackerModule::setADCPedestal()
504 {
505  if (m_pedestalSubtraction == true) {
506  m_adcPedestalFromDB = new DBObjPtr<CDCADCDeltaPedestals>;
507  if (!(*m_adcPedestalFromDB).isValid()) {
508  m_pedestalSubtraction = false;
509  }
510  }
511 
512 }
513 
514 void CDCUnpackerModule::printBuffer(int* buf, int nwords)
515 {
516 
517  for (int j = 0; j < nwords; ++j) {
518  printf(" %.8x", buf[j]);
519  if ((j + 1) % 10 == 0) {
520  printf("\n");
521  }
522  }
523  printf("\n");
524 
525  return;
526 }
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.