12 #include <ecl/modules/eclUnpacker/eclUnpackerModule.h>
18 #include <framework/dataobjects/EventMetaData.h>
21 #include <rawdata/dataobjects/RawECL.h>
24 #include <ecl/dataobjects/ECLDigit.h>
25 #include <ecl/dataobjects/ECLDsp.h>
26 #include <ecl/utility/ECLChannelMapper.h>
27 #include <ecl/utility/ECLDspUtilities.h>
33 #define B2DEBUG_eclunpacker(level, msg) \
34 if (m_debugLevel >= level) {\
35 B2DEBUG(level, msg); \
92 m_unpackingParams("ECLUnpackingParameters", false),
96 setDescription(
"The module reads RawECL data from the DataStore and writes the ECLDigit data");
98 setPropertyFlags(c_ParallelProcessingCertified);
100 addParam(
"InitFileName", m_eclMapperInitFileName,
"Initialization file",
string(
"/ecl/data/ecl_channels_map.txt"));
101 addParam(
"ECLDigitsName", m_eclDigitsName,
"Name of the ECLDigits container",
string(
"ECLDigits"));
102 addParam(
"ECLDspsName", m_eclDspsName,
"Name of the ECLDsp container",
string(
"ECLDsps"));
103 addParam(
"ECLTrigsName", m_eclTrigsName,
"Name of the ECLTrig container",
string(
"ECLTrigs"));
105 addParam(
"storeTrigTime", m_storeTrigTime,
"Store trigger time",
false);
106 addParam(
"storeUnmapped", m_storeUnmapped,
"Store ECLDsp for channels that don't "
107 "exist in ECL mapping",
false);
108 addParam(
"useUnpackingParameters", m_useUnpackingParameters,
109 "Use ECLUnpackingParameters payload",
true);
112 ECLUnpackerModule::~ECLUnpackerModule()
117 void ECLUnpackerModule::initialize()
120 auto& config = LogSystem::Instance().getCurrentLogConfig(PACKAGENAME());
121 m_debugLevel = config.getLogLevel() == LogConfig::c_Debug ? config.getDebugLevel() : 0;
124 m_rawEcl.isRequired();
127 m_eclDigits.registerInDataStore(m_eclDigitsName);
128 if (m_storeTrigTime) {
129 m_eclTrigs.registerInDataStore(m_eclTrigsName);
130 m_relDigitToTrig.registerInDataStore();
132 m_eclDsps.registerInDataStore(m_eclDspsName);
133 m_relDigitToDsp.registerInDataStore();
134 m_eclDsps.registerRelationTo(m_eclDigits);
138 void ECLUnpackerModule::beginRun()
140 m_evtNumReportedMask = 0;
141 m_tagsReportedMask = 0;
142 m_phasesReportedMask = 0;
143 m_badHeaderReportedMask = 0;
146 if (!m_eclMapper.initFromDB()) {
147 B2FATAL(
"ECL Unpacker: Can't initialize eclChannelMapper!");
149 if (!m_unpackingParams.isValid() && m_useUnpackingParameters) {
150 B2FATAL(
"ECL Unpacker: Can't access ECLUnpackingParameters payload");
154 void ECLUnpackerModule::event()
161 if (m_relDigitToTrig) m_relDigitToTrig.clear();
162 if (m_relDigitToDsp) m_relDigitToDsp.clear();
164 if (m_eventMetaData.isValid()) {
165 m_globalEvtNum = m_eventMetaData->getEvent();
170 for (
int i = 0; i < ECL_CRATES; i++) {
171 m_eclTrigsBuffer[i].setTrigId(0);
176 int nRawEclEntries = m_rawEcl.getEntries();
178 B2DEBUG_eclunpacker(22,
"Ecl unpacker event called N_RAW = " << nRawEclEntries);
180 for (
int i = 0; i < nRawEclEntries; i++) {
181 for (
int n = 0; n < m_rawEcl[i]->GetNumEntries(); n++) {
182 readRawECLData(m_rawEcl[ i ], n);
188 ECLTrig* new_ecl_trigs[ECL_CRATES] = {};
189 for (
int i = 0; i < ECL_CRATES; i++) {
190 if (m_eclTrigsBuffer[i].getTrigId() > 0) {
191 new_ecl_trigs[i] = m_eclTrigs.appendNew(m_eclTrigsBuffer[i]);
195 for (
int i = 0; i < m_eclDigits.getEntries(); i++) {
196 int cid = m_eclDigits[i]->getCellId();
197 int crate0 = m_eclMapper.getCrateID(cid) - 1;
198 if (new_ecl_trigs[crate0]) {
199 m_relDigitToTrig.add(i, crate0);
207 void ECLUnpackerModule::endRun()
211 void ECLUnpackerModule::terminate()
216 unsigned int ECLUnpackerModule::readNextCollectorWord()
218 if (m_bufPos == m_bufLength) {
219 B2DEBUG_eclunpacker(22,
"Reached the end of the FINESSE buffer");
220 throw Unexpected_end_of_FINESSE_buffer();
222 unsigned int value = m_bufPtr[m_bufPos];
228 unsigned int ECLUnpackerModule::readNBits(
int bitsToRead)
230 unsigned int val = 0;
232 val = m_bufPtr[m_bufPos] >> m_bitPos;
233 if (m_bitPos + bitsToRead > 31)
234 if (m_bufPos == m_bufLength) {
235 B2ERROR(
"Reached the end of the FINESSE buffer while read compressed ADC data");
237 throw Unexpected_end_of_FINESSE_buffer();
240 val += m_bufPtr[m_bufPos] << (32 - m_bitPos);
241 m_bitPos += bitsToRead;
245 m_bitPos += bitsToRead;
246 if (m_bitPos == 32) {
252 val &= (1 << bitsToRead) - 1;
257 void ECLUnpackerModule::readRawECLData(
RawECL* rawCOPPERData,
int n)
259 int iCrate, iShaper, iChannel, cellID;
262 int adcDataBase, adcDataDiffWidth;
263 int compressMode, shaperDataLength;
264 unsigned int value = 0;
265 unsigned int nRead = 0, ind = 0, indSample = 0;
266 unsigned int nActiveChannelsWithADCData, nADCSamplesPerChannel, nActiveDSPChannels;
268 int dspMask = 0, triggerTag = 0;
270 int adcMask, adcHighMask, dspTime, dspAmplitude, dspQualityFlag;
272 int burstSuppressionMask;
275 std::vector <int> eclWaveformSamples;
277 int nodeID = rawCOPPERData->
GetNodeID(n);
281 for (
int iFINESSE = 0; iFINESSE < ECL_FINESSES_IN_COPPER; iFINESSE++) {
288 if (m_bufLength <= 0)
continue;
291 iCrate = m_eclMapper.getCrateID(nodeID, iFINESSE);
296 B2DEBUG_eclunpacker(21,
"***** iEvt " << m_localEvtNum <<
" node " << std::hex << nodeID);
299 for (
int i = 0; i < m_bufLength; i++) {
300 B2DEBUG_eclunpacker(29,
"" << std::hex << setfill(
'0') << setw(8) << m_bufPtr[i]);
302 B2DEBUG_eclunpacker(21,
"***** ");
308 int eclSubSystem = m_eclMapper.getSubSystem(iCrate);
309 switch (eclSubSystem) {
310 case 0 : nShapers = ECL_BARREL_SHAPERS_IN_CRATE;
break;
311 case 1 : nShapers = ECL_FWD_SHAPERS_IN_CRATE;
break;
312 case 2 : nShapers = ECL_BKW_SHAPERS_IN_CRATE;
break;
313 default : nShapers = ECL_BARREL_SHAPERS_IN_CRATE;
317 burstSuppressionMask = 0;
321 int triggerPhase0 = -1;
322 int triggerTag0 = -1;
325 value = readNextCollectorWord();
326 shapersMask = value & 0xFFF;
327 compressMode = (value & 0xF000) >> 12;
329 B2DEBUG_eclunpacker(22,
"ShapersMask = " << std::hex << shapersMask <<
" compressMode = " << compressMode);
332 for (iShaper = 1; iShaper <= nShapers; iShaper++) {
335 int thisShaperMask = (1 << (iShaper - 1)) & shapersMask;
336 if (thisShaperMask != (1 << (iShaper - 1)))
continue;
339 value = readNextCollectorWord();
340 shaperDataLength = value & 0xFFFF;
341 B2DEBUG_eclunpacker(22,
"iCrate = " << iCrate <<
" iShaper = " << iShaper);
342 B2DEBUG_eclunpacker(22,
"Shaper HEADER = 0x" << std::hex << value <<
" dataLength = " << std::dec << shaperDataLength);
344 if ((value & 0x00FF0000) != 0x00100000) {
345 doBadHeaderReport(iCrate);
346 throw Bad_ShaperDSP_header();
349 value = readNextCollectorWord();
350 burstSuppressionMask |= ((value >> 29) & 1) << (iShaper - 1);
351 nActiveChannelsWithADCData = (value >> 24) & 0x1F;
352 nADCSamplesPerChannel = (value >> 16) & 0x7F;
353 nActiveDSPChannels = (value >> 8) & 0x1F;
354 triggerPhase = value & 0xFF;
357 if (triggerPhase0 == -1) triggerPhase0 = triggerPhase;
358 else if (triggerPhase != triggerPhase0) {
359 doPhasesReport(iCrate, triggerPhase0, triggerPhase);
362 B2DEBUG_eclunpacker(22,
"nActiveADCChannels = " << nActiveChannelsWithADCData <<
" samples " << nADCSamplesPerChannel <<
363 " nActiveDSPChannels "
364 << nActiveDSPChannels);
366 value = readNextCollectorWord();
368 dspMask = (value >> 16) & 0xFFFF;
369 triggerTag = value & 0xFFFF;
370 B2DEBUG_eclunpacker(22,
"DSPMASK = 0x" << std::hex << dspMask <<
" triggerTag " << std::dec << triggerTag);
372 if (triggerTag0 == -1) triggerTag0 = triggerTag;
373 else if (triggerTag != triggerTag0) {
374 doTagsReport(iCrate, triggerTag0, triggerTag);
375 triggerTag0 |= (1 << 16);
378 if (m_globalEvtNum >= 0) {
379 if (triggerTag != (m_globalEvtNum & 0xFFFF)) {
380 doEvtNumReport(iCrate, triggerTag, m_globalEvtNum);
384 value = readNextCollectorWord();
385 adcMask = value & 0xFFFF;
386 adcHighMask = (value >> 16) & 0xFFFF;
387 B2DEBUG_eclunpacker(22,
"ADCMASK = 0x" << std::hex << adcMask <<
" adcHighMask = 0x" << adcHighMask);
389 ECLDigit* newEclDigits[ECL_CHANNELS_IN_SHAPER] = {};
390 int newEclDigitsIdx[ECL_CHANNELS_IN_SHAPER] = {};
394 for (ind = 0; ind < ECL_CHANNELS_IN_SHAPER; ind++) {
396 if (((1 << ind) & dspMask) != (1 << ind))
continue;
398 value = readNextCollectorWord();
399 dspTime = (int)(value << 2) >> 20;
400 dspQualityFlag = (value >> 30) & 0x3;
401 dspAmplitude = (value & 0x3FFFF) - 128;
404 cellID = m_eclMapper.getCellId(iCrate, iShaper, iChannel);
406 if (!isDSPValid(cellID, iCrate, iShaper, iChannel, dspAmplitude, dspTime, dspQualityFlag))
continue;
409 B2DEBUG_eclunpacker(23,
"New eclDigit: cid = " << cellID <<
" amp = " << dspAmplitude <<
" time = " << dspTime <<
" qflag = " <<
413 ECLDigit* newEclDigit = m_eclDigits.appendNew();
414 newEclDigitsIdx[ind] = m_eclDigits.getEntries() - 1;
415 newEclDigits[ind] = newEclDigit;
417 newEclDigit->
setAmp(dspAmplitude);
419 if (dspQualityFlag == 2) {
423 const int chi_mantissa = dspTime & 0x1FF;
424 const int chi_exponent = (dspTime >> 9) & 7;
425 const int chi2 = chi_mantissa << (chi_exponent * 2);
426 newEclDigit->
setChi(chi2);
438 if (nRead != nActiveDSPChannels) {
439 B2ERROR(
"Number of active DSP channels and number of read channels don't match (Corrupted data?)"
440 <<
LogVar(
"nRead", nRead) <<
LogVar(
"nActiveDSP", nActiveDSPChannels));
445 eclWaveformSamples.resize(nADCSamplesPerChannel);
447 for (ind = 0; ind < ECL_CHANNELS_IN_SHAPER; ind++) {
449 if (((1 << ind) & adcMask) != (1 << ind))
continue;
452 adcDataDiffWidth = 0;
453 for (indSample = 0; indSample < nADCSamplesPerChannel; indSample++) {
454 if (compressMode == 0) value = readNextCollectorWord();
456 if (indSample == 0) {
457 value = readNBits(18);
459 B2DEBUG_eclunpacker(24,
"adcDataBase = " << adcDataBase);
460 value = readNBits(5);
461 adcDataDiffWidth = value;
462 B2DEBUG_eclunpacker(24,
"adcDataDiffWidth = " << adcDataDiffWidth);
464 value = readNBits(adcDataDiffWidth);
465 B2DEBUG_eclunpacker(24,
"adcDataOffset = " << value);
466 value += adcDataBase;
469 eclWaveformSamples[indSample] = value;
473 if (nADCSamplesPerChannel > 0) {
475 cellID = m_eclMapper.getCellId(iCrate, iShaper, iChannel);
477 if (cellID > 0 || m_storeUnmapped) {
478 m_eclDsps.appendNew(cellID, eclWaveformSamples);
480 if (m_useUnpackingParameters) {
482 auto params = m_unpackingParams->get(iCrate, iShaper, iChannel);
483 if (params & ECL_OFFLINE_ADC_FIT) {
484 auto result = ECLDspUtilities::shapeFitter(cellID, eclWaveformSamples, triggerPhase0);
485 if (result.quality == 2) result.time = 0;
487 if (!newEclDigits[ind]) {
488 ECLDigit* newEclDigit = m_eclDigits.appendNew();
489 newEclDigits[ind] = newEclDigit;
491 newEclDigit->
setAmp(result.amp);
494 newEclDigit->
setChi(result.chi2);
499 if (newEclDigits[ind]) {
500 int eclDspIdx = m_eclDsps.getEntries() - 1;
501 m_relDigitToDsp.add(newEclDigitsIdx[ind], eclDspIdx);
515 if (nRead != nActiveChannelsWithADCData) {
516 B2ERROR(
"Number of channels with ADC data and "
517 "number of read channels don't match (Corrupted data?)"
518 <<
LogVar(
"active channels", nActiveChannelsWithADCData)
519 <<
LogVar(
"read channels", nRead));
528 if (m_storeTrigTime && shapersMask != 0) {
529 int trigId = iCrate & 0x3F;
530 ECLTrig* eclTrig = &m_eclTrigsBuffer[trigId - 1];
532 trigId |= (burstSuppressionMask & 0xFFF) << 6;
542 B2ERROR(
"Corrupted data from ECL collector");
549 bool ECLUnpackerModule::isDSPValid(
int cellID,
int crate,
int shaper,
int channel,
int,
int,
int quality)
552 if (cellID < 1)
return false;
554 if (m_useUnpackingParameters) {
556 auto params = m_unpackingParams->get(crate, shaper, channel);
557 if (params & ECL_DISCARD_DSP_DATA) {
558 if (params & ECL_KEEP_GOOD_DSP_DATA) {
559 if (quality == 0)
return true;
568 void ECLUnpackerModule::doEvtNumReport(
unsigned int iCrate,
int tag,
int evt_number)
570 if (!evtNumReported(iCrate)) {
571 B2ERROR(
"ECL trigger tag is inconsistent with event number."
572 <<
LogVar(
"crate", iCrate)
573 <<
LogVar(
"trigger tag", tag)
574 <<
LogVar(
"event number", evt_number));
575 m_evtNumReportedMask |= 1L << (iCrate - 1);
578 void ECLUnpackerModule::doTagsReport(
unsigned int iCrate,
int tag0,
int tag1)
580 if (!tagsReported(iCrate)) {
581 B2ERROR(
"Different trigger tags. ECL data is corrupted for whole run probably."
582 <<
LogVar(
"crate", iCrate)
583 <<
LogVar(
"trigger tag0", tag0) <<
LogVar(
"trigger tag1", tag1));
584 m_tagsReportedMask |= 1L << (iCrate - 1);
587 void ECLUnpackerModule::doPhasesReport(
unsigned int iCrate,
int phase0,
int phase1)
589 if (!phasesReported(iCrate)) {
590 B2ERROR(
"Different trigger phases. ECL data is corrupted for whole run probably."
591 <<
LogVar(
"crate", iCrate)
592 <<
LogVar(
"trigger phase0", phase0) <<
LogVar(
"trigger phase1", phase1));
593 m_phasesReportedMask |= 1L << (iCrate - 1);
596 void ECLUnpackerModule::doBadHeaderReport(
unsigned int iCrate)
598 if (!badHeaderReported(iCrate)) {
599 B2ERROR(
"Bad shaper header."
600 <<
LogVar(
"crate", iCrate));
601 m_badHeaderReportedMask |= 1L << (iCrate - 1);