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