Belle II Software  release-08-00-10
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 
34 CDCUnpackerModule::CDCUnpackerModule() : Module()
35 {
36  //Set module properties
37  setDescription("CDCUnpacker generates CDCHit from Raw data.");
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 
61 {
62 }
63 
65 {
66  m_dataLengthError = false;
67  m_dataSizeError = false;
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 
90 {
91  if (m_enablePrintOut == true) {
92  B2INFO("CDCUnpacker: beginRun() called.");
93  }
94 
95 
96  loadMap();
98 }
99 
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  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 
441 {
442  if (m_enablePrintOut == true) {
443  B2INFO("CDCUnpacker : End run.");
444  }
445 }
446 
448 {
449  if (m_enablePrintOut == true) {
450  B2INFO("CDCUnpacker : Terminated.");
451  }
452 
455 }
456 
457 
458 WireID CDCUnpackerModule::getWireID(int iBoard, int iCh) const
459 {
460  return m_map[iBoard][iCh];
461 }
462 
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 
504 {
505  if (m_pedestalSubtraction == true) {
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
StoreArray< RawCDC > m_rawCDCs
Input array for CDC Raw.
bool m_enableDatabase
Enable/Disable to read the channel map from the database.
std::vector< unsigned short > m_buffer
Short ward buffer of CDC event block.
int m_channelTrig
Channel for the trigger.
bool m_dataSizeError
True if data size error between CDCFE and COPPER has been already reported.
std::string m_rawCDCName
Name of the RawCDC dataobject (suppressed mode).
void initialize() override
Initializes the Module.
DBArray< CDCChannelMap > * m_channelMapFromDB
Channel map retrieved from DB.
StoreArray< CDCRawHitWaveForm > m_CDCRawHitWaveForms
Raw hit waveforms.
void printBuffer(int *buf, int nwords)
Print out the CDC data block in hex.
int getTriggerNumber()
Getter for trigger number.
void event() override
Event action (main routine).
StoreArray< CDCRawHit > m_CDCRawHits
Raw hits.
bool m_subtractTrigTiming
Enable/Disable to subtract the trigger timing from TDCs.
bool m_dataLengthError
True if data length error has been already reported.
void endRun() override
End run action.
void terminate() override
Termination action.
int getTriggerTime()
Getter for trigger time in nsec.
int m_tdcOffset
TDC offset (nsec).
std::string m_xmlMapFileName
Name of the assignment map of FE board channel to the cell.
WireID m_map[300][48]
Assignment map of FE board channel to the cell.
int getDataType()
Getter for CDC data mode.
std::string m_cdcRawHitName
Name of the CDCRawHit dataobject (suppressed mode).
bool m_pedestalSubtraction
Whether pedestal is subtracted (true) or not (false).
void beginRun() override
Begin run action.
DBObjPtr< CDCADCDeltaPedestals > * m_adcPedestalFromDB
ADC delta pedestal.
int m_boardIDTrig
Board ID for the trigger.
bool m_enableStoreCDCRawHit
Enable/Disable to store CDCRawHit.
int m_tdcAuxOffset
TDC auxiliary offset (nsec).
int getDataLength()
Getter for data length in byte.
void loadMap()
Load FE channel to cell ID map.
WireID getWireID(int iBoard, int iCh) const
Getter of Wire ID.
bool m_enablePrintOut
Enable/Disable to print out the data to the terminal.
bool isValidBoardChannel(WireID wireId)
Check if the hit wire is valid or not.
std::string m_cdcRawHitWaveFormName
Name of the CDCRawHit dataobject (raw data mode).
void setCDCPacketHeader(const int *buf)
Set CDC Packet header.
virtual ~CDCUnpackerModule()
Destructor of the module.
bool m_enable2ndHit
Enable/Disable to 2nd hit output.
int getBoardId()
Getter for FE board ID.
std::string m_cdcHitName
Tree name of the CDCHit object.
void setADCPedestal()
Set DBobject of ADC delta pedestal.
StoreArray< CDCHit > m_CDCHits
CDC hits.
Class for accessing arrays of objects in the database.
Definition: DBArray.h:26
Class for accessing objects in the database.
Definition: DBObjPtr.h:21
static std::string findFile(const std::string &path, bool silent=false)
Search for given file or directory in local or central release directory, and return absolute path if...
Definition: FileSystem.cc:148
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:80
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.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
#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.