10 #include <ecl/modules/eclUnpacker/eclUnpackerModule.h>
16 #include <framework/dataobjects/EventMetaData.h>
19 #include <rawdata/dataobjects/RawECL.h>
22 #include <ecl/dataobjects/ECLDigit.h>
23 #include <ecl/dataobjects/ECLDsp.h>
24 #include <ecl/utility/ECLDspUtilities.h>
30 #define B2DEBUG_eclunpacker(level, msg) \
31 if (m_debugLevel >= level) {\
32 B2DEBUG(level, msg); \
89 m_unpackingParams("ECLUnpackingParameters", false),
93 setDescription(
"The module reads RawECL data from the DataStore and writes the ECLDigit data");
95 setPropertyFlags(c_ParallelProcessingCertified);
97 addParam(
"InitFileName", m_eclMapperInitFileName,
"Initialization file",
string(
"/ecl/data/ecl_channels_map.txt"));
98 addParam(
"ECLDigitsName", m_eclDigitsName,
"Name of the ECLDigits container",
string(
"ECLDigits"));
99 addParam(
"ECLDspsName", m_eclDspsName,
"Name of the ECLDsp container",
string(
"ECLDsps"));
100 addParam(
"ECLTrigsName", m_eclTrigsName,
"Name of the ECLTrig container",
string(
"ECLTrigs"));
102 addParam(
"storeTrigTime", m_storeTrigTime,
"Store trigger time",
false);
103 addParam(
"storeUnmapped", m_storeUnmapped,
"Store ECLDsp for channels that don't "
104 "exist in ECL mapping",
false);
105 addParam(
"useUnpackingParameters", m_useUnpackingParameters,
106 "Use ECLUnpackingParameters payload",
true);
109 void ECLUnpackerModule::initialize()
112 auto& config = LogSystem::Instance().getCurrentLogConfig(PACKAGENAME());
113 m_debugLevel = config.getLogLevel() == LogConfig::c_Debug ? config.getDebugLevel() : 0;
116 m_rawEcl.isRequired();
119 m_eclDigits.registerInDataStore(m_eclDigitsName);
120 if (m_storeTrigTime) {
121 m_eclTrigs.registerInDataStore(m_eclTrigsName);
122 m_relDigitToTrig.registerInDataStore();
124 m_eclDsps.registerInDataStore(m_eclDspsName);
125 m_relDigitToDsp.registerInDataStore();
126 m_eclDsps.registerRelationTo(m_eclDigits);
130 void ECLUnpackerModule::beginRun()
132 m_evtNumReportedMask = 0;
133 m_tagsReportedMask = 0;
134 m_phasesReportedMask = 0;
135 m_badHeaderReportedMask = 0;
138 if (!m_eclMapper.initFromDB()) {
139 B2FATAL(
"ECL Unpacker: Can't initialize eclChannelMapper!");
141 if (!m_unpackingParams.isValid() && m_useUnpackingParameters) {
142 B2FATAL(
"ECL Unpacker: Can't access ECLUnpackingParameters payload");
146 void ECLUnpackerModule::event()
153 if (m_relDigitToTrig) m_relDigitToTrig.clear();
154 if (m_relDigitToDsp) m_relDigitToDsp.clear();
156 if (m_eventMetaData.isValid()) {
157 m_globalEvtNum = m_eventMetaData->getEvent();
162 for (
int i = 0; i < ECL_CRATES; i++) {
163 m_eclTrigsBuffer[i].setTrigId(0);
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);
180 ECLTrig* new_ecl_trigs[ECL_CRATES] = {};
181 for (
int i = 0; i < ECL_CRATES; i++) {
182 if (m_eclTrigsBuffer[i].getTrigId() > 0) {
183 new_ecl_trigs[i] = m_eclTrigs.appendNew(m_eclTrigsBuffer[i]);
187 for (
int i = 0; i < m_eclDigits.getEntries(); i++) {
188 int cid = m_eclDigits[i]->getCellId();
189 int crate0 = m_eclMapper.getCrateID(cid) - 1;
190 if (new_ecl_trigs[crate0]) {
191 m_relDigitToTrig.add(i, crate0);
199 void ECLUnpackerModule::endRun()
203 void ECLUnpackerModule::terminate()
208 unsigned int ECLUnpackerModule::readNextCollectorWord()
210 if (m_bufPos == m_bufLength) {
211 B2DEBUG_eclunpacker(22,
"Reached the end of the FINESSE buffer");
212 throw Unexpected_end_of_FINESSE_buffer();
214 unsigned int value = m_bufPtr[m_bufPos];
220 unsigned int ECLUnpackerModule::readNBits(
int bitsToRead)
222 unsigned int val = 0;
224 val = m_bufPtr[m_bufPos] >> m_bitPos;
225 if (m_bitPos + bitsToRead > 31)
226 if (m_bufPos == m_bufLength) {
227 B2ERROR(
"Reached the end of the FINESSE buffer while read compressed ADC data");
229 throw Unexpected_end_of_FINESSE_buffer();
232 val += m_bufPtr[m_bufPos] << (32 - m_bitPos);
233 m_bitPos += bitsToRead;
237 m_bitPos += bitsToRead;
238 if (m_bitPos == 32) {
244 val &= (1 << bitsToRead) - 1;
249 void ECLUnpackerModule::readRawECLData(
RawECL* rawCOPPERData,
int n)
251 int iCrate, iShaper, iChannel, cellID;
254 int adcDataBase, adcDataDiffWidth;
255 int compressMode, shaperDataLength;
256 unsigned int value = 0;
257 unsigned int nRead = 0, ind = 0, indSample = 0;
258 unsigned int nActiveChannelsWithADCData, nADCSamplesPerChannel, nActiveDSPChannels;
260 int dspMask = 0, triggerTag = 0;
262 int adcMask, adcHighMask, dspTime, dspAmplitude, dspQualityFlag;
264 int burstSuppressionMask;
267 std::vector <int> eclWaveformSamples;
269 int nodeID = rawCOPPERData->
GetNodeID(n);
272 int collectorsInNode = -1;
274 bool pcie40Data =
false;
275 if (channelsCount == 4) {
277 collectorsInNode = 2;
278 }
else if (channelsCount == 48) {
280 collectorsInNode = 18;
281 if (nodeID == BECL_ID + 3) {
282 collectorsInNode = 16;
285 B2FATAL(
"The maximum number of channels per readout board is invalid."
286 <<
LogVar(
"Number of channels", channelsCount));
290 for (
int iFINESSE = 0; iFINESSE < collectorsInNode; iFINESSE++) {
297 if (m_bufLength <= 0)
continue;
300 iCrate = m_eclMapper.getCrateID(nodeID, iFINESSE, pcie40Data);
305 B2DEBUG_eclunpacker(21,
"***** iEvt " << m_localEvtNum <<
" node " << std::hex << nodeID);
308 for (
int i = 0; i < m_bufLength; i++) {
309 B2DEBUG_eclunpacker(29,
"" << std::hex << setfill(
'0') << setw(8) << m_bufPtr[i]);
311 B2DEBUG_eclunpacker(21,
"***** ");
317 int eclSubSystem = m_eclMapper.getSubSystem(iCrate);
318 switch (eclSubSystem) {
319 case 0 : nShapers = ECL_BARREL_SHAPERS_IN_CRATE;
break;
320 case 1 : nShapers = ECL_FWD_SHAPERS_IN_CRATE;
break;
321 case 2 : nShapers = ECL_BKW_SHAPERS_IN_CRATE;
break;
322 default : nShapers = ECL_BARREL_SHAPERS_IN_CRATE;
326 burstSuppressionMask = 0;
330 int triggerPhase0 = -1;
331 int triggerTag0 = -1;
334 value = readNextCollectorWord();
335 shapersMask = value & 0xFFF;
336 compressMode = (value & 0xF000) >> 12;
338 B2DEBUG_eclunpacker(22,
"ShapersMask = " << std::hex << shapersMask <<
" compressMode = " << compressMode);
341 for (iShaper = 1; iShaper <= nShapers; iShaper++) {
344 int thisShaperMask = (1 << (iShaper - 1)) & shapersMask;
345 if (thisShaperMask != (1 << (iShaper - 1)))
continue;
348 value = readNextCollectorWord();
349 shaperDataLength = value & 0xFFFF;
350 B2DEBUG_eclunpacker(22,
"iCrate = " << iCrate <<
" iShaper = " << iShaper);
351 B2DEBUG_eclunpacker(22,
"Shaper HEADER = 0x" << std::hex << value <<
" dataLength = " << std::dec << shaperDataLength);
353 if ((value & 0x00FF0000) != 0x00100000) {
354 doBadHeaderReport(iCrate);
355 throw Bad_ShaperDSP_header();
358 value = readNextCollectorWord();
359 burstSuppressionMask |= ((value >> 29) & 1) << (iShaper - 1);
360 nActiveChannelsWithADCData = (value >> 24) & 0x1F;
361 nADCSamplesPerChannel = (value >> 16) & 0x7F;
362 nActiveDSPChannels = (value >> 8) & 0x1F;
363 triggerPhase = value & 0xFF;
366 if (triggerPhase0 == -1) triggerPhase0 = triggerPhase;
367 else if (triggerPhase != triggerPhase0) {
368 doPhasesReport(iCrate, triggerPhase0, triggerPhase);
371 B2DEBUG_eclunpacker(22,
"nActiveADCChannels = " << nActiveChannelsWithADCData <<
" samples " << nADCSamplesPerChannel <<
372 " nActiveDSPChannels "
373 << nActiveDSPChannels);
375 value = readNextCollectorWord();
377 dspMask = (value >> 16) & 0xFFFF;
378 triggerTag = value & 0xFFFF;
379 B2DEBUG_eclunpacker(22,
"DSPMASK = 0x" << std::hex << dspMask <<
" triggerTag " << std::dec << triggerTag);
381 if (triggerTag0 == -1) triggerTag0 = triggerTag;
382 else if (triggerTag != triggerTag0) {
383 doTagsReport(iCrate, triggerTag0, triggerTag);
384 triggerTag0 |= (1 << 16);
387 if (m_globalEvtNum >= 0) {
388 if (triggerTag != (m_globalEvtNum & 0xFFFF)) {
389 doEvtNumReport(iCrate, triggerTag, m_globalEvtNum);
393 value = readNextCollectorWord();
394 adcMask = value & 0xFFFF;
395 adcHighMask = (value >> 16) & 0xFFFF;
396 B2DEBUG_eclunpacker(22,
"ADCMASK = 0x" << std::hex << adcMask <<
" adcHighMask = 0x" << adcHighMask);
398 ECLDigit* newEclDigits[ECL_CHANNELS_IN_SHAPER] = {};
399 int newEclDigitsIdx[ECL_CHANNELS_IN_SHAPER] = {};
403 for (ind = 0; ind < ECL_CHANNELS_IN_SHAPER; ind++) {
405 if (((1 << ind) & dspMask) != (1 << ind))
continue;
407 value = readNextCollectorWord();
408 dspTime = (int)(value << 2) >> 20;
409 dspQualityFlag = (value >> 30) & 0x3;
410 dspAmplitude = (value & 0x3FFFF) - 128;
413 cellID = m_eclMapper.getCellId(iCrate, iShaper, iChannel);
415 if (!isDSPValid(cellID, iCrate, iShaper, iChannel, dspAmplitude, dspTime, dspQualityFlag))
continue;
418 B2DEBUG_eclunpacker(23,
"New eclDigit: cid = " << cellID <<
" amp = " << dspAmplitude <<
" time = " << dspTime <<
" qflag = " <<
422 ECLDigit* newEclDigit = m_eclDigits.appendNew();
423 newEclDigitsIdx[ind] = m_eclDigits.getEntries() - 1;
424 newEclDigits[ind] = newEclDigit;
426 newEclDigit->
setAmp(dspAmplitude);
428 if (dspQualityFlag == 2) {
432 const int chi_mantissa = dspTime & 0x1FF;
433 const int chi_exponent = (dspTime >> 9) & 7;
434 const int chi2 = chi_mantissa << (chi_exponent * 2);
435 newEclDigit->
setChi(chi2);
447 if (nRead != nActiveDSPChannels) {
448 B2ERROR(
"Number of active DSP channels and number of read channels don't match (Corrupted data?)"
449 <<
LogVar(
"nRead", nRead) <<
LogVar(
"nActiveDSP", nActiveDSPChannels));
454 eclWaveformSamples.resize(nADCSamplesPerChannel);
456 for (ind = 0; ind < ECL_CHANNELS_IN_SHAPER; ind++) {
458 if (((1 << ind) & adcMask) != (1 << ind))
continue;
461 adcDataDiffWidth = 0;
462 for (indSample = 0; indSample < nADCSamplesPerChannel; indSample++) {
463 if (compressMode == 0) value = readNextCollectorWord();
465 if (indSample == 0) {
466 value = readNBits(18);
468 B2DEBUG_eclunpacker(24,
"adcDataBase = " << adcDataBase);
469 value = readNBits(5);
470 adcDataDiffWidth = value;
471 B2DEBUG_eclunpacker(24,
"adcDataDiffWidth = " << adcDataDiffWidth);
473 value = readNBits(adcDataDiffWidth);
474 B2DEBUG_eclunpacker(24,
"adcDataOffset = " << value);
475 value += adcDataBase;
478 eclWaveformSamples[indSample] = value;
482 if (nADCSamplesPerChannel > 0) {
484 cellID = m_eclMapper.getCellId(iCrate, iShaper, iChannel);
486 if (cellID > 0 || m_storeUnmapped) {
487 m_eclDsps.appendNew(cellID, eclWaveformSamples);
489 if (m_useUnpackingParameters) {
491 auto params = m_unpackingParams->get(iCrate, iShaper, iChannel);
492 if (params & ECL_OFFLINE_ADC_FIT) {
493 auto result = ECLDspUtilities::shapeFitter(cellID, eclWaveformSamples, triggerPhase0);
494 if (result.quality == 2) result.time = 0;
496 if (!newEclDigits[ind]) {
497 ECLDigit* newEclDigit = m_eclDigits.appendNew();
498 newEclDigits[ind] = newEclDigit;
500 newEclDigit->
setAmp(result.amp);
503 newEclDigit->
setChi(result.chi2);
508 if (newEclDigits[ind]) {
509 int eclDspIdx = m_eclDsps.getEntries() - 1;
510 m_relDigitToDsp.add(newEclDigitsIdx[ind], eclDspIdx);
524 if (nRead != nActiveChannelsWithADCData) {
525 B2ERROR(
"Number of channels with ADC data and "
526 "number of read channels don't match (Corrupted data?)"
527 <<
LogVar(
"active channels", nActiveChannelsWithADCData)
528 <<
LogVar(
"read channels", nRead));
537 if (m_storeTrigTime && shapersMask != 0) {
538 int trigId = iCrate & 0x3F;
539 ECLTrig* eclTrig = &m_eclTrigsBuffer[trigId - 1];
541 trigId |= (burstSuppressionMask & 0xFFF) << 6;
551 B2ERROR(
"Corrupted data from ECL collector");
558 bool ECLUnpackerModule::isDSPValid(
int cellID,
int crate,
int shaper,
int channel,
int,
int,
int quality)
561 if (cellID < 1)
return false;
563 if (m_useUnpackingParameters) {
565 auto params = m_unpackingParams->get(crate, shaper, channel);
566 if (params & ECL_DISCARD_DSP_DATA) {
567 if (params & ECL_KEEP_GOOD_DSP_DATA) {
568 if (quality == 0)
return true;
577 void ECLUnpackerModule::doEvtNumReport(
unsigned int iCrate,
int tag,
int evt_number)
579 if (!evtNumReported(iCrate)) {
580 B2ERROR(
"ECL trigger tag is inconsistent with event number."
581 <<
LogVar(
"crate", iCrate)
582 <<
LogVar(
"trigger tag", tag)
583 <<
LogVar(
"event number", evt_number));
584 m_evtNumReportedMask |= 1L << (iCrate - 1);
587 void ECLUnpackerModule::doTagsReport(
unsigned int iCrate,
int tag0,
int tag1)
589 if (!tagsReported(iCrate)) {
590 B2ERROR(
"Different trigger tags. ECL data is corrupted for whole run probably."
591 <<
LogVar(
"crate", iCrate)
592 <<
LogVar(
"trigger tag0", tag0) <<
LogVar(
"trigger tag1", tag1));
593 m_tagsReportedMask |= 1L << (iCrate - 1);
596 void ECLUnpackerModule::doPhasesReport(
unsigned int iCrate,
int phase0,
int phase1)
598 if (!phasesReported(iCrate)) {
599 B2ERROR(
"Different trigger phases. ECL data is corrupted for whole run probably."
600 <<
LogVar(
"crate", iCrate)
601 <<
LogVar(
"trigger phase0", phase0) <<
LogVar(
"trigger phase1", phase1));
602 m_phasesReportedMask |= 1L << (iCrate - 1);
605 void ECLUnpackerModule::doBadHeaderReport(
unsigned int iCrate)
607 if (!badHeaderReported(iCrate)) {
608 B2ERROR(
"Bad shaper header."
609 <<
LogVar(
"crate", iCrate));
610 m_badHeaderReportedMask |= 1L << (iCrate - 1);
In the store you can park objects that have to be accessed by various modules.
Class to store ECL digitized hits (output of ECLDigi) relation to ECLHit filled in ecl/modules/eclDig...
void setAmp(int Amp)
Set Fitting Amplitude.
void setTimeFit(int TimeFit)
Set Fitting Time.
void setCellId(int CellId)
Set Cell ID.
void setQuality(int Quality)
Set Fitting Quality.
void setChi(int Chi)
Set Chi-squared.
Class to store ECLTrig, still need to be study relation to ECLHit filled in ecl/modules/eclDigitizer/...
void setTrigTag(int TrigTag)
Set Trig Time (crate Id)
void setTrigId(int TrigId)
Set TrigID.
void setTimeTrig(double TimeTrig)
Set Triger Tag (crate Id)
The Raw ECL class Class for RawCOPPER class data taken by ECL Currently, this class is almost same as...
Class to store variables with their name which were sent to the logging service.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
int GetDetectorNwords(int n, int finesse_num)
get Detector buffer length
int * GetDetectorBuffer(int n, int finesse_num)
get Detector buffer
unsigned int GetNodeID(int n)
get node-ID from data
int GetMaxNumOfCh(int n)
Get the max number of channels in a readout board.
Abstract base class for different kinds of events.