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