Belle II Software  release-06-00-14
eclPackerModule.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 //This module
9 #include <ecl/modules/eclPacker/eclPackerModule.h>
10 
11 //STL
12 #include <ios>
13 #include <iomanip>
14 
15 //Framework
16 #include <framework/logging/Logger.h>
17 
18 //ECL
19 #include <ecl/dataobjects/ECLDigit.h>
20 #include <ecl/dataobjects/ECLDsp.h>
21 
22 //Raw data
23 #include <rawdata/dataobjects/RawECL.h>
24 
25 using namespace std;
26 using namespace Belle2;
27 using namespace ECL;
28 
29 REG_MODULE(ECLPacker)
30 
31 ECLPackerModule::ECLPackerModule() :
32  m_bufPos(0),
33  m_bufLength(0),
34  m_bitPos(0),
35  m_EclWaveformSamples(),
36  m_eclMapper(),
37  m_eclRawCOPPERs("", DataStore::c_Event),
38  adcBuffer_temp(),
39  collectorMaskArray(),
40  shaperMaskArray(),
41  shaperADCMaskArray(),
42  shaperNWaveform(),
43  shaperNHits(),
44  iEclDigIndices(),
45  iEclWfIndices()
46 {
47  setDescription("The module reads ECLDigits from the DataStore and writes ECLRaw data.");
48  addParam("InitFileName", m_eclMapperInitFileName, "Initialization file", string("/ecl/data/ecl_channels_map.txt"));
49  addParam("RawCOPPERsName", m_eclRawCOPPERsName, "Name of the RawECL container", string("RawECLs"));
50  addParam("CompressMode", m_compressMode, "compress mode for ADC samples", true);
51  addParam("AmpThreshold", m_ampThreshold, "Amplitude threshold", -50);
52  addParam("PackWfRareFactor", m_WaveformRareFactor, "Pack ADC samples for one of N events. No waveform is packed if 0", 100);
53 
54  m_EvtNum = 0;
55 }
56 
57 ECLPackerModule::~ECLPackerModule()
58 {
59 }
60 
62 {
63  // require input data
64  m_eclDigits.isRequired();
65  m_eclDsps.isOptional();
66 
67  // register output container in data store
68  m_eclRawCOPPERs.registerInDataStore(m_eclRawCOPPERsName);
69 
70  B2INFO("ECL Packer: Compress mode = " << m_compressMode);
71 }
72 
74 {
75  // Initialize channel mapper at run start to account for possible
76  // changes in ECL mapping between runs.
77  if (!m_eclMapper.initFromDB()) {
78  B2FATAL("ECL Packer: Can't initialize eclChannelMapper!");
79  }
80 
81  //TODO
82 }
83 
85 {
86 
87  B2DEBUG(50, "EclPacker:: event called ");
88  // output data
89  m_eclRawCOPPERs.clear();
90 
91  B2DEBUG(50, "EclPacker:: output data arrays created");
92 
93  int nActiveChannelsWithADCData, nActiveDSPChannels;
94  int triggerPhase = 0, dspMask = 0;
95 
96  // get total number of hits
97  int nEclDigits = m_eclDigits.getEntries();
98  int nEclWaveform = m_eclDsps.getEntries();
99 
100  for (int i = 0; i < ECL_CRATES; i++) {
101  collectorMaskArray[i] = 0;
102  for (int j = 0; j < ECL_BARREL_SHAPERS_IN_CRATE; j++) {
103  shaperMaskArray[i][j] = 0;
104  shaperNHits[i][j] = 0;
105  shaperADCMaskArray[i][j] = 0;
106  shaperNWaveform[i][j] = 0;
107  }
108  }
109 
110  for (int j = 0; j < ECL_TOTAL_CHANNELS; j++) {
111  iEclDigIndices[j] = -1;
112  iEclWfIndices[j] = -1;
113  }
114 
115  B2DEBUG(100, "EclPacker:: N_Digits = " << nEclDigits);
116  B2DEBUG(100, "EclPacker:: N_Waveforms = " << nEclWaveform);
117 
118  int iCOPPER, iFINESSE, iCrate, iShaper, iChannel, nShapers;
119 
120  B2DEBUG(100, "EclPacker:: Hits ======>> ");
121  int tot_dsp_hits = 0;
122  // fill number of hits, masks and fill correspondance between cellID and index in container
123  for (int i_digit = 0; i_digit < nEclDigits; i_digit++) {
124  int cid = m_eclDigits[i_digit]->getCellId();
125  int amp = m_eclDigits[i_digit]->getAmp();
126 
127  if (amp < m_ampThreshold) continue;
128 
129  //TODO: Threshold
130  iCrate = m_eclMapper.getCrateID(cid);
131  iShaper = m_eclMapper.getShaperPosition(cid);
132  iChannel = m_eclMapper.getShaperChannel(cid);
133 
134  if (iCrate < 1 && iShaper < 1 && iChannel < 1) {
135  B2ERROR("Wrong crate/shaper/channel ids: " << iCrate << " " << iShaper << " " << iChannel << " for CID " << cid);
136  throw eclPacker_internal_error();
137  }
138  collectorMaskArray[iCrate - 1] |= (1 << (iShaper - 1));
139 
140  shaperMaskArray[iCrate - 1][iShaper - 1] |= (1 << (iChannel - 1));
141  shaperNHits[iCrate - 1][iShaper - 1]++;
142 
143  iEclDigIndices[cid - 1] = i_digit;
144  tot_dsp_hits++;
145  }
146 
147  B2DEBUG(100, "ECL Packer:: N Hits above threshold = " << tot_dsp_hits << " nWaveforms = " << nEclWaveform);
148 
149  if (m_WaveformRareFactor != 0)
150  if (m_EvtNum % m_WaveformRareFactor == 0) {
151  B2DEBUG(100, "ECL Packer:: Pack waveform data for this event: " << m_EvtNum);
152  for (int i_wf = 0; i_wf < nEclWaveform; i_wf++) {
153  int cid = m_eclDsps[i_wf]->getCellId();
154  iCrate = m_eclMapper.getCrateID(cid);
155  iShaper = m_eclMapper.getShaperPosition(cid);
156  iChannel = m_eclMapper.getShaperChannel(cid);
157 
158  //check corresponding amplitude in ecl digits
159  int amp = 0;
160  for (int i_digit = 0; i_digit < nEclDigits; i_digit++) {
161  if (m_eclDigits[i_digit]->getCellId() == cid) {
162  amp = m_eclDigits[i_digit]->getAmp();
163  break;
164  }
165  }
166  if (amp < m_ampThreshold) continue;
167 
168  shaperADCMaskArray[iCrate - 1][iShaper - 1] |= (1 << (iChannel - 1));
169  shaperNWaveform[iCrate - 1][iShaper - 1]++;
170 
171  iEclWfIndices[cid - 1] = i_wf;
172  }
173  }
174 
175  // fill rawCOPPERPacker data
176  RawCOPPERPackerInfo rawcprpacker_info;
177  rawcprpacker_info.exp_num = 0;
178  rawcprpacker_info.run_subrun_num = 1; // run number : 14bits, subrun # : 8bits
179  rawcprpacker_info.eve_num = m_EvtNum;
180  rawcprpacker_info.tt_ctime = 0x7123456; //??? (copy-past from CDC)
181  rawcprpacker_info.tt_utime = 0xF1234567; //???
182  rawcprpacker_info.b2l_ctime = 0x7654321; //???
183 
184 
185  B2DEBUG(100, "EclPacker:: proceed COPPERs... ");
186  B2DEBUG(100, "EclPacker:: ECL_COPPERS = " << ECL_COPPERS);
187 
188  //cycle over all coppers
189  for (iCOPPER = 1; iCOPPER <= ECL_COPPERS; iCOPPER++) {
190 
191  std::vector <unsigned int> buff[ECL_FINESSES_IN_COPPER];
192  for (int i = 0; i < ECL_FINESSES_IN_COPPER; i++) buff[i].clear();
193 
194  int iCOPPERNode = (iCOPPER <= ECL_BARREL_COPPERS) ? BECL_ID + iCOPPER : EECL_ID + iCOPPER - ECL_BARREL_COPPERS;
195 
196  //check if at least one of FINESSES have hits
197  int icr1 = m_eclMapper.getCrateID(iCOPPERNode, 0);
198  int icr2 = m_eclMapper.getCrateID(iCOPPERNode, 1);
199  B2DEBUG(200, "iCOPPERNode = 0x" << std::hex << iCOPPERNode << std::dec << " nCrate1 = " << icr1 << " nCrate2 = " << icr2);
200  if (!(collectorMaskArray[icr1 - 1] || collectorMaskArray[icr2 - 1])) continue;
201 
202  rawcprpacker_info.node_id = iCOPPERNode;
203  // Create RawECL object
204 
205  int nwords[2] = {0, 0};
206  const int finesseHeaderNWords = 3;
207 
208  //cycle over finesses in copper
209  for (iFINESSE = 0; iFINESSE < ECL_FINESSES_IN_COPPER; iFINESSE++) {
210  iCrate = m_eclMapper.getCrateID(iCOPPERNode, iFINESSE);
211 
212  nShapers = m_eclMapper.getNShapersInCrate(iCrate);
213  if (!nShapers) B2ERROR("Ecl packer:: Wrong shapers number " << nShapers);
214 
215  if (!shaperMaskArray[iCrate - 1]) continue;
216  B2DEBUG(200, "Pack data for iCrate = " << iCrate << " nShapers = " << nShapers);
217 
218  // write EclCollector header to the buffer
219  unsigned int eclCollectorHeader = (1 << nShapers) - 1;
220  if (m_compressMode) eclCollectorHeader += (1 << 12);
221  buff[iFINESSE].push_back(eclCollectorHeader);
222 
223  for (iShaper = 1; iShaper <= nShapers; iShaper++) {
224 
225  nActiveDSPChannels = shaperNHits[iCrate - 1][iShaper - 1];
226  B2DEBUG(200, "iCrate = " << iCrate << " iShaper = " << iShaper << " nActiveDSPChannels = " << nActiveDSPChannels);
227  nActiveChannelsWithADCData = shaperNWaveform[iCrate - 1][iShaper - 1];
228  B2DEBUG(200, "nActiveChannelsWithADCData = " << nActiveChannelsWithADCData);
229 
230  // write 4 words of shaper header
231 
232  unsigned int shaperDataLength = 4 + nActiveDSPChannels + nActiveChannelsWithADCData * ECL_ADC_SAMPLES_PER_CHANNEL;
233  // fill shaperDsp header
234  unsigned int shaper_header_w0 = (0x10 << 16) + (shaperDataLength & 0xFFFF);
235  buff[iFINESSE].push_back(shaper_header_w0);
236 
237  triggerPhase = 0; //?????
238  unsigned int shaper_header_w1 = (nActiveChannelsWithADCData & 0x1F) << 24;
239  shaper_header_w1 |= (ECL_ADC_SAMPLES_PER_CHANNEL & 0x7F) << 16;
240  shaper_header_w1 |= (nActiveDSPChannels & 0x1F) << 8;
241  shaper_header_w1 |= triggerPhase;
242  buff[iFINESSE].push_back(shaper_header_w1);
243 
244  dspMask = shaperMaskArray[iCrate - 1][iShaper - 1];
245  B2DEBUG(200, "dspMask = " << std::hex << dspMask);
246  unsigned int shaper_header_w2 = (dspMask & 0xFFFF) << 16;
247  shaper_header_w2 |= (m_EvtNum & 0xFFFF); // trigger tag
248  buff[iFINESSE].push_back(shaper_header_w2);
249 
250  unsigned int adcMask = shaperADCMaskArray[iCrate - 1][iShaper - 1];
251  B2DEBUG(100, "adcMask = " << std::hex << adcMask);
252  unsigned int shaper_header_w3 = (adcMask & 0xFFFF);
253  buff[iFINESSE].push_back(shaper_header_w3);
254 
255  // cycle over shaper channels and push DSP data to buffer
256  for (iChannel = 1; iChannel <= ECL_CHANNELS_IN_SHAPER; iChannel++) {
257 
258  const int cid = m_eclMapper.getCellId(iCrate, iShaper, iChannel);
259 
260  if (cid < 1) continue;
261 
262  const int i_digit = iEclDigIndices[cid - 1];
263  if (i_digit < 0) continue;
264  const int qua = m_eclDigits[i_digit]->getQuality();
265  const int amp = m_eclDigits[i_digit]->getAmp();
266  const int chi = m_eclDigits[i_digit]->getChi();
267  int tim = 0;
268  if (qua == 2) {
269  // pack chisquare
270 
271  int chi_mantissa = 0, chi_exponent = 0;
272  int n_bits = ceil(log2(double(chi)));
273  if (n_bits > 9) {
274  chi_exponent = ceil(float(n_bits - 9) / 2.0);
275  chi_mantissa = chi >> chi_exponent * 2;
276  } else {
277  chi_exponent = 0;
278  chi_mantissa = chi;
279  }
280  tim = (chi_exponent << 9) | chi_mantissa;
281  } else {
282  // pack time
283  tim = m_eclDigits[i_digit]->getTimeFit();
284  }
285  unsigned int hit_data = ((qua & 3) << 30) & 0xC0000000;
286  hit_data |= (tim & 0xFFF) << 18;
287  hit_data |= ((amp + 128) & 0x3FFFF);
288  buff[iFINESSE].push_back(hit_data);
289 
290  B2DEBUG(100, "cid = " << cid << " amp = " << amp << " tim = " << tim);
291  }
292 
293  for (int i = 0; i < ECL_CHANNELS_IN_SHAPER; i++) adcBuffer_temp[i] = 0;
295  setBuffLength(ECL_ADC_SAMPLES_PER_CHANNEL * ECL_CHANNELS_IN_SHAPER);
296  for (iChannel = 1; iChannel <= ECL_CHANNELS_IN_SHAPER; iChannel++) {
297  int cid = m_eclMapper.getCellId(iCrate, iShaper, iChannel);
298  if (cid < 1) continue;
299  int i_wf = iEclWfIndices[cid - 1];
300  if (i_wf < 0) continue;
301  B2DEBUG(200, "i_wf = " << i_wf);
302  m_eclDsps[i_wf]->getDspA(m_EclWaveformSamples); // Check this method in implementation of ECLDsp.h!!!
303 
304  if (m_compressMode) {
305  unsigned int adc_data_base = 0;
306  unsigned int adc_data_diff_width = 0;
307 
308  // calculate adc_data_base and adc_data_diff_width for compressed mode
309  unsigned int ampMin = m_EclWaveformSamples[0];
310  unsigned int ampMax = m_EclWaveformSamples[0];
311 
312  for (unsigned int iSample = 0; iSample < ECL_ADC_SAMPLES_PER_CHANNEL; iSample++) {
313  if ((unsigned int) m_EclWaveformSamples[iSample] > ampMax) ampMax = m_EclWaveformSamples[iSample];
314  if ((unsigned int) m_EclWaveformSamples[iSample] < ampMin) ampMin = m_EclWaveformSamples[iSample];
315  }
316 
317  B2DEBUG(250, "ampMin = " << ampMin << " ampMax = " << ampMax);
318 
319  adc_data_base = ampMin & 0x3FFFF;
320  writeNBits(adcBuffer_temp, adc_data_base, 18);
321  adc_data_diff_width = (unsigned int)(log2((float)ampMax - (float)ampMin)) + 1;
322  adc_data_diff_width &= 0x1F;
323  writeNBits(adcBuffer_temp, adc_data_diff_width, 5);
324 
325  B2DEBUG(250, "Width = " << adc_data_diff_width << " Base = " << adc_data_base);
326 
327  for (unsigned int iSample = 0; iSample < ECL_ADC_SAMPLES_PER_CHANNEL; iSample++) {
328  unsigned int adc_data_offset = m_EclWaveformSamples[iSample] - adc_data_base;
329  B2DEBUG(250, "offset = " << adc_data_offset);
330  writeNBits(adcBuffer_temp, adc_data_offset, adc_data_diff_width);
331  }
332  } else {
333  for (unsigned int iSample = 0; iSample < ECL_ADC_SAMPLES_PER_CHANNEL; iSample++) {
334  buff[iFINESSE].push_back(m_EclWaveformSamples[iSample]);
335  }
336 
337  }
338 
339  }
340  if (m_compressMode) {
341  if (m_bitPos > 0) m_bufPos++;
342  for (int i = 0; i < m_bufPos; i++) {
343  buff[iFINESSE].push_back(adcBuffer_temp[i]);
344 
345  B2DEBUG(500, "Buff word " << std::hex << adcBuffer_temp[i]);
346  }
347  }
348  }
349  }
350 
351  RawECL* newRawECL = m_eclRawCOPPERs.appendNew();
352 
353  nwords[0] = buff[0].size();
354  nwords[1] = buff[1].size();
355 
356  buff[0][0] |= (nwords[0] - finesseHeaderNWords) * 4;
357  buff[1][0] |= (nwords[1] - finesseHeaderNWords) * 4;
358 
359  B2DEBUG(100, "**** iEvt = " << m_EvtNum << " node= " << iCOPPERNode);
360  for (unsigned int i = 0; i < 2; i++)
361  for (unsigned int j = 0; j < buff[i].size(); j++) {
362  B2DEBUG(210, ">> " << std::hex << setfill('0') << setw(8) << buff[i][j]);
363  }
364 
365  B2DEBUG(100, "Call PackDetectorBuf");
366  newRawECL->PackDetectorBuf((int*)buff[0].data(), nwords[0], (int*)buff[1].data(), nwords[1],
367  nullptr, 0, nullptr, 0, rawcprpacker_info);
368  }
369  m_EvtNum++;
370 }
371 
373 {
374  //TODO
375 }
376 
378 {
379 }
380 
382 {
383  m_bufLength = bufLength;
384 }
385 
387 {
388  m_bufPos = 0;
389  m_bitPos = 0;
390 }
391 
392 void ECLPackerModule::writeNBits(unsigned int* buff, unsigned int value, unsigned int bitsToWrite)
393 {
394  if (!bitsToWrite) return;
395 
396  if (value > (unsigned int)(1 << bitsToWrite) - 1) {
397  B2ERROR("Error compressing ADC samples: tying to write too long word");
398  throw Write_adc_samples_error();
399  }
400 
401  if (m_bitPos + bitsToWrite > 32)
402  if (m_bufPos == m_bufLength) {
403  B2ERROR("Error compressing ADC samples: unexpectedly reach end of buffer");
404  throw Write_adc_samples_error();
405  } else {
406  unsigned tmpval = (1 << m_bitPos) - 1;
407  buff[m_bufPos] &= tmpval;
408  buff[m_bufPos] += value << m_bitPos;
409  m_bufPos++;
410  buff[m_bufPos] = value >> (32 - m_bitPos);
411  m_bitPos += bitsToWrite;
412  m_bitPos -= 32;
413  }
414  else {
415  unsigned tmpval = (1 << m_bitPos) - 1;
416  buff[m_bufPos] &= tmpval;
417  buff[m_bufPos] += value << m_bitPos;
418  m_bitPos += bitsToWrite;
419  if (m_bitPos == 32) {
420  m_bufPos++;
421  m_bitPos -= 32;
422  }
423  }
424 
425 }
In the store you can park objects that have to be accessed by various modules.
Definition: DataStore.h:51
StoreArray< ECLDsp > m_eclDsps
ECLDSP dataStore object.
int m_ampThreshold
DSP amplitude threshold.
int iEclDigIndices[ECL::ECL_TOTAL_CHANNELS]
indexes of related eclDigits
int shaperNHits[ECL::ECL_CRATES][ECL::ECL_BARREL_SHAPERS_IN_CRATE]
Number of hits per shaper.
int shaperMaskArray[ECL::ECL_CRATES][ECL::ECL_BARREL_SHAPERS_IN_CRATE]
triggered shapers
int m_EvtNum
Event number.
ECL::ECLChannelMapper m_eclMapper
channel mapper
int iEclWfIndices[ECL::ECL_TOTAL_CHANNELS]
indexes of related waveforms
int shaperADCMaskArray[ECL::ECL_CRATES][ECL::ECL_BARREL_SHAPERS_IN_CRATE]
shapers with ADC data
virtual void initialize() override
initialize
int m_bufPos
position in the data array
int m_EclWaveformSamples[ECL_ADC_SAMPLES_PER_CHANNEL]
array of ADC samples
virtual void event() override
event
int shaperNWaveform[ECL::ECL_CRATES][ECL::ECL_BARREL_SHAPERS_IN_CRATE]
Number of waveforms per shaper.
int m_WaveformRareFactor
the rate of writing of the ADC samples
virtual void endRun() override
endRun
int m_bitPos
bit position for bit-by-bit data read
virtual void terminate() override
terminate
StoreArray< ECLDigit > m_eclDigits
ECLDigit dataStore object.
void setBuffLength(int bufLength)
set buffer length
virtual void beginRun() override
beginRun
StoreArray< RawECL > m_eclRawCOPPERs
Output data
bool m_compressMode
eneble/disable compression of waveform data
int m_bufLength
length data
int collectorMaskArray[ECL::ECL_CRATES]
array of triggered collectors
void writeNBits(unsigned int *buff, unsigned int value, unsigned int bitsToWrite)
write N bits to the collector buffer
void resetBuffPosition()
reset current position in the buffer
std::string m_eclRawCOPPERsName
name of output collection for RawCOPPER
unsigned int adcBuffer_temp[ECL::ECL_CHANNELS_IN_SHAPER *ECL_ADC_SAMPLES_PER_CHANNEL]
temporary buffer to store ADC data
bool initFromDB()
Initialize channel mapper from the conditions database.
int getCrateID(int iCOPPERNode, int iFINESSE)
get crate number by given COPPER node number and FINESSE number
int getNShapersInCrate(int iCrate)
get number of ShaperDSP modules in the given VME crate number
int getCellId(int iCrate, int iShaper, int iChannel)
get CellId by given crate number, shaper position in the crate and DSP channel number in the shaper
int getShaperChannel(int cellID)
get number of DSP channel in the shaper by given number of CellId
int getShaperPosition(int cellID)
get position of the shaper in the crate by given CellId
struct to contain header information used by RawCOPPERFormat::Packer()
unsigned int b2l_ctime
32bit unitx time at trigger timing distributed by FTSW. For details, see Nakao-san's belle2link user ...
unsigned int eve_num
Run # and subrun # ( 22bit )
unsigned int tt_ctime
Node ID (32bit)
unsigned int tt_utime
27bit clock ticks at trigger timing distributed by FTSW. For details, see Nakao-san's belle2link user...
unsigned int node_id
Event Number (32bit)
unsigned int run_subrun_num
Experiment number (10bit)
unsigned int exp_num
Experiment number (10bit)
void PackDetectorBuf(int *detector_buf_1st, int nwords_1st, int *detector_buf_2nd, int nwords_2nd, int *detector_buf_3rd, int nwords_3rd, int *detector_buf_4th, int nwords_4th, RawCOPPERPackerInfo rawcprpacker_info)
Packer for RawCOPPER class Pack data (format ver.
Definition: RawCOPPER.cc:183
The Raw ECL class Class for RawCOPPER class data taken by ECL Currently, this class is almost same as...
Definition: RawECL.h:26
#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.