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/ECLTrig.h>
26 #include <ecl/dataobjects/ECLDsp.h>
27 #include <ecl/utility/ECLChannelMapper.h>
28 #include <ecl/utility/ECLDspUtilities.h>
34 #define B2DEBUG_eclunpacker(level, msg) \
35 if (m_debugLevel >= level) {\
36 B2DEBUG(level, msg); \
93 m_unpackingParams("ECLUnpackingParameters", false),
97 setDescription(
"The module reads RawECL data from the DataStore and writes the ECLDigit data");
99 setPropertyFlags(c_ParallelProcessingCertified);
101 addParam(
"InitFileName", m_eclMapperInitFileName,
"Initialization file",
string(
"/ecl/data/ecl_channels_map.txt"));
102 addParam(
"ECLDigitsName", m_eclDigitsName,
"Name of the ECLDigits container",
string(
"ECLDigits"));
103 addParam(
"ECLDspsName", m_eclDspsName,
"Name of the ECLDsp container",
string(
"ECLDsps"));
104 addParam(
"ECLTrigsName", m_eclTrigsName,
"Name of the ECLTrig container",
string(
"ECLTrigs"));
106 addParam(
"storeTrigTime", m_storeTrigTime,
"Store trigger time",
false);
107 addParam(
"storeUnmapped", m_storeUnmapped,
"Store ECLDsp for channels that don't "
108 "exist in ECL mapping",
false);
109 addParam(
"useUnpackingParameters", m_useUnpackingParameters,
110 "Use ECLUnpackingParameters payload",
true);
113 ECLUnpackerModule::~ECLUnpackerModule()
118 void ECLUnpackerModule::initialize()
121 auto& config = LogSystem::Instance().getCurrentLogConfig(PACKAGENAME());
122 m_debugLevel = config.getLogLevel() == LogConfig::c_Debug ? config.getDebugLevel() : 0;
125 m_rawEcl.isRequired();
128 m_eclDigits.registerInDataStore(m_eclDigitsName);
129 if (m_storeTrigTime) {
130 m_eclTrigs.registerInDataStore(m_eclTrigsName);
131 m_eclDigits.registerRelationTo(m_eclTrigs);
133 m_eclDsps.registerInDataStore(m_eclDspsName);
134 m_eclDigits.registerRelationTo(m_eclDsps);
135 m_eclDsps.registerRelationTo(m_eclDigits);
139 void ECLUnpackerModule::beginRun()
141 m_evtNumReportedMask = 0;
142 m_tagsReportedMask = 0;
143 m_phasesReportedMask = 0;
144 m_badHeaderReportedMask = 0;
147 if (!m_eclMapper.initFromDB()) {
148 B2FATAL(
"ECL Unpacker: Can't initialize eclChannelMapper!");
150 if (!m_unpackingParams.isValid() && m_useUnpackingParameters) {
151 B2FATAL(
"ECL Unpacker: Can't access ECLUnpackingParameters payload");
155 void ECLUnpackerModule::event()
162 if (m_eventMetaData.isValid()) {
163 m_globalEvtNum = m_eventMetaData->getEvent();
168 int nRawEclEntries = m_rawEcl.getEntries();
170 B2DEBUG_eclunpacker(22,
"Ecl unpacker event called N_RAW = " << nRawEclEntries);
172 for (
int i = 0; i < nRawEclEntries; i++) {
173 for (
int n = 0; n < m_rawEcl[i]->GetNumEntries(); n++) {
174 readRawECLData(m_rawEcl[ i ], n);
182 void ECLUnpackerModule::endRun()
186 void ECLUnpackerModule::terminate()
191 unsigned int ECLUnpackerModule::readNextCollectorWord()
193 if (m_bufPos == m_bufLength) {
194 B2DEBUG_eclunpacker(22,
"Reached the end of the FINESSE buffer");
195 throw Unexpected_end_of_FINESSE_buffer();
197 unsigned int value = m_bufPtr[m_bufPos];
203 unsigned int ECLUnpackerModule::readNBits(
int bitsToRead)
205 unsigned int val = 0;
207 val = m_bufPtr[m_bufPos] >> m_bitPos;
208 if (m_bitPos + bitsToRead > 31)
209 if (m_bufPos == m_bufLength) {
210 B2ERROR(
"Reached the end of the FINESSE buffer while read compressed ADC data");
212 throw Unexpected_end_of_FINESSE_buffer();
215 val += m_bufPtr[m_bufPos] << (32 - m_bitPos);
216 m_bitPos += bitsToRead;
220 m_bitPos += bitsToRead;
221 if (m_bitPos == 32) {
227 val &= (1 << bitsToRead) - 1;
232 void ECLUnpackerModule::readRawECLData(
RawECL* rawCOPPERData,
int n)
234 int iCrate, iShaper, iChannel, cellID;
237 int adcDataBase, adcDataDiffWidth;
238 int compressMode, shaperDataLength;
239 unsigned int value = 0;
240 unsigned int nRead = 0, ind = 0, indSample = 0;
241 unsigned int nActiveChannelsWithADCData, nADCSamplesPerChannel, nActiveDSPChannels;
243 int dspMask = 0, triggerTag = 0;
245 int adcMask, adcHighMask, dspTime, dspAmplitude, dspQualityFlag;
247 int burstSuppressionMask;
250 std::vector <int> eclWaveformSamples;
252 int nodeID = rawCOPPERData->
GetNodeID(n);
256 for (
int iFINESSE = 0; iFINESSE < ECL_FINESSES_IN_COPPER; iFINESSE++) {
263 if (m_bufLength <= 0)
continue;
266 iCrate = m_eclMapper.getCrateID(nodeID, iFINESSE);
271 B2DEBUG_eclunpacker(21,
"***** iEvt " << m_localEvtNum <<
" node " << std::hex << nodeID);
274 for (
int i = 0; i < m_bufLength; i++) {
275 B2DEBUG_eclunpacker(29,
"" << std::hex << setfill(
'0') << setw(8) << m_bufPtr[i]);
277 B2DEBUG_eclunpacker(21,
"***** ");
283 int eclSubSystem = m_eclMapper.getSubSystem(iCrate);
284 switch (eclSubSystem) {
285 case 0 : nShapers = ECL_BARREL_SHAPERS_IN_CRATE;
break;
286 case 1 : nShapers = ECL_FWD_SHAPERS_IN_CRATE;
break;
287 case 2 : nShapers = ECL_BKW_SHAPERS_IN_CRATE;
break;
288 default : nShapers = ECL_BARREL_SHAPERS_IN_CRATE;
294 burstSuppressionMask = 0;
298 int triggerPhase0 = -1;
299 int triggerTag0 = -1;
302 value = readNextCollectorWord();
303 shapersMask = value & 0xFFF;
304 compressMode = (value & 0xF000) >> 12;
306 B2DEBUG_eclunpacker(22,
"ShapersMask = " << std::hex << shapersMask <<
" compressMode = " << compressMode);
309 if (m_storeTrigTime && shapersMask != 0) eclTrig = m_eclTrigs.appendNew();
312 for (iShaper = 1; iShaper <= nShapers; iShaper++) {
315 int thisShaperMask = (1 << (iShaper - 1)) & shapersMask;
316 if (thisShaperMask != (1 << (iShaper - 1)))
continue;
319 value = readNextCollectorWord();
320 shaperDataLength = value & 0xFFFF;
321 B2DEBUG_eclunpacker(22,
"iCrate = " << iCrate <<
" iShaper = " << iShaper);
322 B2DEBUG_eclunpacker(22,
"Shaper HEADER = 0x" << std::hex << value <<
" dataLength = " << std::dec << shaperDataLength);
324 if ((value & 0x00FF0000) != 0x00100000) {
325 doBadHeaderReport(iCrate);
326 throw Bad_ShaperDSP_header();
329 value = readNextCollectorWord();
330 burstSuppressionMask |= ((value >> 29) & 1) << (iShaper - 1);
331 nActiveChannelsWithADCData = (value >> 24) & 0x1F;
332 nADCSamplesPerChannel = (value >> 16) & 0x7F;
333 nActiveDSPChannels = (value >> 8) & 0x1F;
334 triggerPhase = value & 0xFF;
337 if (triggerPhase0 == -1) triggerPhase0 = triggerPhase;
338 else if (triggerPhase != triggerPhase0) {
339 doPhasesReport(iCrate, triggerPhase0, triggerPhase);
342 B2DEBUG_eclunpacker(22,
"nActiveADCChannels = " << nActiveChannelsWithADCData <<
" samples " << nADCSamplesPerChannel <<
343 " nActiveDSPChannels "
344 << nActiveDSPChannels);
346 value = readNextCollectorWord();
348 dspMask = (value >> 16) & 0xFFFF;
349 triggerTag = value & 0xFFFF;
350 B2DEBUG_eclunpacker(22,
"DSPMASK = 0x" << std::hex << dspMask <<
" triggerTag " << std::dec << triggerTag);
352 if (triggerTag0 == -1) triggerTag0 = triggerTag;
353 else if (triggerTag != triggerTag0) {
354 doTagsReport(iCrate, triggerTag0, triggerTag);
355 triggerTag0 |= (1 << 16);
358 if (m_globalEvtNum >= 0) {
359 if (triggerTag != (m_globalEvtNum & 0xFFFF)) {
360 doEvtNumReport(iCrate, triggerTag, m_globalEvtNum);
364 value = readNextCollectorWord();
365 adcMask = value & 0xFFFF;
366 adcHighMask = (value >> 16) & 0xFFFF;
367 B2DEBUG_eclunpacker(22,
"ADCMASK = 0x" << std::hex << adcMask <<
" adcHighMask = 0x" << adcHighMask);
371 for (ind = 0; ind < ECL_CHANNELS_IN_SHAPER; ind++) {
373 if (((1 << ind) & dspMask) != (1 << ind))
continue;
375 value = readNextCollectorWord();
376 dspTime = (int)(value << 2) >> 20;
377 dspQualityFlag = (value >> 30) & 0x3;
378 dspAmplitude = (value & 0x3FFFF) - 128;
381 cellID = m_eclMapper.getCellId(iCrate, iShaper, iChannel);
383 if (!isDSPValid(cellID, iCrate, iShaper, iChannel, dspAmplitude, dspTime, dspQualityFlag))
continue;
386 B2DEBUG_eclunpacker(23,
"New eclDigit: cid = " << cellID <<
" amp = " << dspAmplitude <<
" time = " << dspTime <<
" qflag = " <<
390 ECLDigit* newEclDigit = m_eclDigits.appendNew();
392 newEclDigit->
setAmp(dspAmplitude);
394 if (dspQualityFlag == 2) {
398 const int chi_mantissa = dspTime & 0x1FF;
399 const int chi_exponent = (dspTime >> 9) & 7;
400 const int chi2 = chi_mantissa << (chi_exponent * 2);
401 newEclDigit->
setChi(chi2);
414 if (nRead != nActiveDSPChannels) {
415 B2ERROR(
"Number of active DSP channels and number of read channels don't match (Corrupted data?)"
416 <<
LogVar(
"nRead", nRead) <<
LogVar(
"nActiveDSP", nActiveDSPChannels));
423 for (ind = 0; ind < ECL_CHANNELS_IN_SHAPER; ind++) {
425 if (((1 << ind) & adcMask) != (1 << ind))
continue;
428 adcDataDiffWidth = 0;
429 eclWaveformSamples.clear();
430 for (indSample = 0; indSample < nADCSamplesPerChannel; indSample++) {
431 if (compressMode == 0) value = readNextCollectorWord();
433 if (indSample == 0) {
434 value = readNBits(18);
436 B2DEBUG_eclunpacker(24,
"adcDataBase = " << adcDataBase);
437 value = readNBits(5);
438 adcDataDiffWidth = value;
439 B2DEBUG_eclunpacker(24,
"adcDataDiffWidth = " << adcDataDiffWidth);
441 value = readNBits(adcDataDiffWidth);
442 B2DEBUG_eclunpacker(24,
"adcDataOffset = " << value);
443 value += adcDataBase;
446 eclWaveformSamples.push_back(value);
450 if (eclWaveformSamples.size() > 0) {
452 if (eclWaveformSamples.size() != nADCSamplesPerChannel)
453 B2ERROR(
"Wrong number of ADC samples. Actual number of read samples "
454 " != number of samples in header "
455 <<
LogVar(
"Actual number of read samples", eclWaveformSamples.size())
456 <<
LogVar(
"Number of samples in header", nADCSamplesPerChannel));
458 cellID = m_eclMapper.getCellId(iCrate, iShaper, iChannel);
460 if (cellID > 0 || m_storeUnmapped) {
461 ECLDsp* newEclDsp = m_eclDsps.appendNew(cellID, eclWaveformSamples);
463 if (m_useUnpackingParameters) {
465 auto params = m_unpackingParams->get(iCrate, iShaper, iChannel);
466 if (params & ECL_OFFLINE_ADC_FIT) {
467 auto result = ECLDspUtilities::shapeFitter(cellID, eclWaveformSamples, triggerPhase0);
468 if (result.quality == 2) result.time = 0;
471 for (
auto& newEclDigit : m_eclDigits) {
472 if (newEclDsp->
getCellId() == newEclDigit.getCellId()) {
473 newEclDigit.setAmp(result.amp);
474 newEclDigit.setTimeFit(result.time);
475 newEclDigit.setQuality(result.quality);
476 newEclDigit.setChi(result.chi2);
482 ECLDigit* newEclDigit = m_eclDigits.appendNew();
484 newEclDigit->
setAmp(result.amp);
487 newEclDigit->
setChi(result.chi2);
493 for (
auto& newEclDigit : m_eclDigits) {
494 if (newEclDsp->
getCellId() == newEclDigit.getCellId()) {
495 newEclDigit.addRelationTo(newEclDsp);
511 if (nRead != nActiveChannelsWithADCData) {
512 B2ERROR(
"Number of channels with ADC data and "
513 "number of read channels don't match (Corrupted data?)"
514 <<
LogVar(
"active channels", nActiveChannelsWithADCData)
515 <<
LogVar(
"read channels", nRead));
525 int trigId = iCrate & 0x3F;
526 trigId |= (burstSuppressionMask & 0xFFF) << 6;
536 B2ERROR(
"Corrupted data from ECL collector");
543 bool ECLUnpackerModule::isDSPValid(
int cellID,
int crate,
int shaper,
int channel,
int,
int,
int quality)
546 if (cellID < 1)
return false;
548 if (m_useUnpackingParameters) {
550 auto params = m_unpackingParams->get(crate, shaper, channel);
551 if (params & ECL_DISCARD_DSP_DATA) {
552 if (params & ECL_KEEP_GOOD_DSP_DATA) {
553 if (quality == 0)
return true;
562 void ECLUnpackerModule::doEvtNumReport(
unsigned int iCrate,
int tag,
int evt_number)
564 if (!evtNumReported(iCrate)) {
565 B2ERROR(
"ECL trigger tag is inconsistent with event number."
566 <<
LogVar(
"crate", iCrate)
567 <<
LogVar(
"trigger tag", tag)
568 <<
LogVar(
"event number", evt_number));
569 m_evtNumReportedMask |= 1L << (iCrate - 1);
572 void ECLUnpackerModule::doTagsReport(
unsigned int iCrate,
int tag0,
int tag1)
574 if (!tagsReported(iCrate)) {
575 B2ERROR(
"Different trigger tags. ECL data is corrupted for whole run probably."
576 <<
LogVar(
"crate", iCrate)
577 <<
LogVar(
"trigger tag0", tag0) <<
LogVar(
"trigger tag1", tag1));
578 m_tagsReportedMask |= 1L << (iCrate - 1);
581 void ECLUnpackerModule::doPhasesReport(
unsigned int iCrate,
int phase0,
int phase1)
583 if (!phasesReported(iCrate)) {
584 B2ERROR(
"Different trigger phases. ECL data is corrupted for whole run probably."
585 <<
LogVar(
"crate", iCrate)
586 <<
LogVar(
"trigger phase0", phase0) <<
LogVar(
"trigger phase1", phase1));
587 m_phasesReportedMask |= 1L << (iCrate - 1);
590 void ECLUnpackerModule::doBadHeaderReport(
unsigned int iCrate)
592 if (!badHeaderReported(iCrate)) {
593 B2ERROR(
"Bad shaper header."
594 <<
LogVar(
"crate", iCrate));
595 m_badHeaderReportedMask |= 1L << (iCrate - 1);