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/ECLChannelMapper.h>
25 #include <ecl/utility/ECLDspUtilities.h>
31 #define B2DEBUG_eclunpacker(level, msg) \
32 if (m_debugLevel >= level) {\
33 B2DEBUG(level, msg); \
90 m_unpackingParams("ECLUnpackingParameters", false),
94 setDescription(
"The module reads RawECL data from the DataStore and writes the ECLDigit data");
96 setPropertyFlags(c_ParallelProcessingCertified);
98 addParam(
"InitFileName", m_eclMapperInitFileName,
"Initialization file",
string(
"/ecl/data/ecl_channels_map.txt"));
99 addParam(
"ECLDigitsName", m_eclDigitsName,
"Name of the ECLDigits container",
string(
"ECLDigits"));
100 addParam(
"ECLDspsName", m_eclDspsName,
"Name of the ECLDsp container",
string(
"ECLDsps"));
101 addParam(
"ECLTrigsName", m_eclTrigsName,
"Name of the ECLTrig container",
string(
"ECLTrigs"));
103 addParam(
"storeTrigTime", m_storeTrigTime,
"Store trigger time",
false);
104 addParam(
"storeUnmapped", m_storeUnmapped,
"Store ECLDsp for channels that don't "
105 "exist in ECL mapping",
false);
106 addParam(
"useUnpackingParameters", m_useUnpackingParameters,
107 "Use ECLUnpackingParameters payload",
true);
110 ECLUnpackerModule::~ECLUnpackerModule()
115 void ECLUnpackerModule::initialize()
118 auto& config = LogSystem::Instance().getCurrentLogConfig(PACKAGENAME());
119 m_debugLevel = config.getLogLevel() == LogConfig::c_Debug ? config.getDebugLevel() : 0;
122 m_rawEcl.isRequired();
125 m_eclDigits.registerInDataStore(m_eclDigitsName);
126 if (m_storeTrigTime) {
127 m_eclTrigs.registerInDataStore(m_eclTrigsName);
128 m_relDigitToTrig.registerInDataStore();
130 m_eclDsps.registerInDataStore(m_eclDspsName);
131 m_relDigitToDsp.registerInDataStore();
132 m_eclDsps.registerRelationTo(m_eclDigits);
136 void ECLUnpackerModule::beginRun()
138 m_evtNumReportedMask = 0;
139 m_tagsReportedMask = 0;
140 m_phasesReportedMask = 0;
141 m_badHeaderReportedMask = 0;
144 if (!m_eclMapper.initFromDB()) {
145 B2FATAL(
"ECL Unpacker: Can't initialize eclChannelMapper!");
147 if (!m_unpackingParams.isValid() && m_useUnpackingParameters) {
148 B2FATAL(
"ECL Unpacker: Can't access ECLUnpackingParameters payload");
152 void ECLUnpackerModule::event()
159 if (m_relDigitToTrig) m_relDigitToTrig.clear();
160 if (m_relDigitToDsp) m_relDigitToDsp.clear();
162 if (m_eventMetaData.isValid()) {
163 m_globalEvtNum = m_eventMetaData->getEvent();
168 for (
int i = 0; i < ECL_CRATES; i++) {
169 m_eclTrigsBuffer[i].setTrigId(0);
174 int nRawEclEntries = m_rawEcl.getEntries();
176 B2DEBUG_eclunpacker(22,
"Ecl unpacker event called N_RAW = " << nRawEclEntries);
178 for (
int i = 0; i < nRawEclEntries; i++) {
179 for (
int n = 0; n < m_rawEcl[i]->GetNumEntries(); n++) {
180 readRawECLData(m_rawEcl[ i ], n);
186 ECLTrig* new_ecl_trigs[ECL_CRATES] = {};
187 for (
int i = 0; i < ECL_CRATES; i++) {
188 if (m_eclTrigsBuffer[i].getTrigId() > 0) {
189 new_ecl_trigs[i] = m_eclTrigs.appendNew(m_eclTrigsBuffer[i]);
193 for (
int i = 0; i < m_eclDigits.getEntries(); i++) {
194 int cid = m_eclDigits[i]->getCellId();
195 int crate0 = m_eclMapper.getCrateID(cid) - 1;
196 if (new_ecl_trigs[crate0]) {
197 m_relDigitToTrig.add(i, crate0);
205 void ECLUnpackerModule::endRun()
209 void ECLUnpackerModule::terminate()
214 unsigned int ECLUnpackerModule::readNextCollectorWord()
216 if (m_bufPos == m_bufLength) {
217 B2DEBUG_eclunpacker(22,
"Reached the end of the FINESSE buffer");
218 throw Unexpected_end_of_FINESSE_buffer();
220 unsigned int value = m_bufPtr[m_bufPos];
226 unsigned int ECLUnpackerModule::readNBits(
int bitsToRead)
228 unsigned int val = 0;
230 val = m_bufPtr[m_bufPos] >> m_bitPos;
231 if (m_bitPos + bitsToRead > 31)
232 if (m_bufPos == m_bufLength) {
233 B2ERROR(
"Reached the end of the FINESSE buffer while read compressed ADC data");
235 throw Unexpected_end_of_FINESSE_buffer();
238 val += m_bufPtr[m_bufPos] << (32 - m_bitPos);
239 m_bitPos += bitsToRead;
243 m_bitPos += bitsToRead;
244 if (m_bitPos == 32) {
250 val &= (1 << bitsToRead) - 1;
255 void ECLUnpackerModule::readRawECLData(
RawECL* rawCOPPERData,
int n)
257 int iCrate, iShaper, iChannel, cellID;
260 int adcDataBase, adcDataDiffWidth;
261 int compressMode, shaperDataLength;
262 unsigned int value = 0;
263 unsigned int nRead = 0, ind = 0, indSample = 0;
264 unsigned int nActiveChannelsWithADCData, nADCSamplesPerChannel, nActiveDSPChannels;
266 int dspMask = 0, triggerTag = 0;
268 int adcMask, adcHighMask, dspTime, dspAmplitude, dspQualityFlag;
270 int burstSuppressionMask;
273 std::vector <int> eclWaveformSamples;
275 int nodeID = rawCOPPERData->
GetNodeID(n);
279 for (
int iFINESSE = 0; iFINESSE < ECL_FINESSES_IN_COPPER; iFINESSE++) {
286 if (m_bufLength <= 0)
continue;
289 iCrate = m_eclMapper.getCrateID(nodeID, iFINESSE);
294 B2DEBUG_eclunpacker(21,
"***** iEvt " << m_localEvtNum <<
" node " << std::hex << nodeID);
297 for (
int i = 0; i < m_bufLength; i++) {
298 B2DEBUG_eclunpacker(29,
"" << std::hex << setfill(
'0') << setw(8) << m_bufPtr[i]);
300 B2DEBUG_eclunpacker(21,
"***** ");
306 int eclSubSystem = m_eclMapper.getSubSystem(iCrate);
307 switch (eclSubSystem) {
308 case 0 : nShapers = ECL_BARREL_SHAPERS_IN_CRATE;
break;
309 case 1 : nShapers = ECL_FWD_SHAPERS_IN_CRATE;
break;
310 case 2 : nShapers = ECL_BKW_SHAPERS_IN_CRATE;
break;
311 default : nShapers = ECL_BARREL_SHAPERS_IN_CRATE;
315 burstSuppressionMask = 0;
319 int triggerPhase0 = -1;
320 int triggerTag0 = -1;
323 value = readNextCollectorWord();
324 shapersMask = value & 0xFFF;
325 compressMode = (value & 0xF000) >> 12;
327 B2DEBUG_eclunpacker(22,
"ShapersMask = " << std::hex << shapersMask <<
" compressMode = " << compressMode);
330 for (iShaper = 1; iShaper <= nShapers; iShaper++) {
333 int thisShaperMask = (1 << (iShaper - 1)) & shapersMask;
334 if (thisShaperMask != (1 << (iShaper - 1)))
continue;
337 value = readNextCollectorWord();
338 shaperDataLength = value & 0xFFFF;
339 B2DEBUG_eclunpacker(22,
"iCrate = " << iCrate <<
" iShaper = " << iShaper);
340 B2DEBUG_eclunpacker(22,
"Shaper HEADER = 0x" << std::hex << value <<
" dataLength = " << std::dec << shaperDataLength);
342 if ((value & 0x00FF0000) != 0x00100000) {
343 doBadHeaderReport(iCrate);
344 throw Bad_ShaperDSP_header();
347 value = readNextCollectorWord();
348 burstSuppressionMask |= ((value >> 29) & 1) << (iShaper - 1);
349 nActiveChannelsWithADCData = (value >> 24) & 0x1F;
350 nADCSamplesPerChannel = (value >> 16) & 0x7F;
351 nActiveDSPChannels = (value >> 8) & 0x1F;
352 triggerPhase = value & 0xFF;
355 if (triggerPhase0 == -1) triggerPhase0 = triggerPhase;
356 else if (triggerPhase != triggerPhase0) {
357 doPhasesReport(iCrate, triggerPhase0, triggerPhase);
360 B2DEBUG_eclunpacker(22,
"nActiveADCChannels = " << nActiveChannelsWithADCData <<
" samples " << nADCSamplesPerChannel <<
361 " nActiveDSPChannels "
362 << nActiveDSPChannels);
364 value = readNextCollectorWord();
366 dspMask = (value >> 16) & 0xFFFF;
367 triggerTag = value & 0xFFFF;
368 B2DEBUG_eclunpacker(22,
"DSPMASK = 0x" << std::hex << dspMask <<
" triggerTag " << std::dec << triggerTag);
370 if (triggerTag0 == -1) triggerTag0 = triggerTag;
371 else if (triggerTag != triggerTag0) {
372 doTagsReport(iCrate, triggerTag0, triggerTag);
373 triggerTag0 |= (1 << 16);
376 if (m_globalEvtNum >= 0) {
377 if (triggerTag != (m_globalEvtNum & 0xFFFF)) {
378 doEvtNumReport(iCrate, triggerTag, m_globalEvtNum);
382 value = readNextCollectorWord();
383 adcMask = value & 0xFFFF;
384 adcHighMask = (value >> 16) & 0xFFFF;
385 B2DEBUG_eclunpacker(22,
"ADCMASK = 0x" << std::hex << adcMask <<
" adcHighMask = 0x" << adcHighMask);
387 ECLDigit* newEclDigits[ECL_CHANNELS_IN_SHAPER] = {};
388 int newEclDigitsIdx[ECL_CHANNELS_IN_SHAPER] = {};
392 for (ind = 0; ind < ECL_CHANNELS_IN_SHAPER; ind++) {
394 if (((1 << ind) & dspMask) != (1 << ind))
continue;
396 value = readNextCollectorWord();
397 dspTime = (int)(value << 2) >> 20;
398 dspQualityFlag = (value >> 30) & 0x3;
399 dspAmplitude = (value & 0x3FFFF) - 128;
402 cellID = m_eclMapper.getCellId(iCrate, iShaper, iChannel);
404 if (!isDSPValid(cellID, iCrate, iShaper, iChannel, dspAmplitude, dspTime, dspQualityFlag))
continue;
407 B2DEBUG_eclunpacker(23,
"New eclDigit: cid = " << cellID <<
" amp = " << dspAmplitude <<
" time = " << dspTime <<
" qflag = " <<
411 ECLDigit* newEclDigit = m_eclDigits.appendNew();
412 newEclDigitsIdx[ind] = m_eclDigits.getEntries() - 1;
413 newEclDigits[ind] = newEclDigit;
415 newEclDigit->
setAmp(dspAmplitude);
417 if (dspQualityFlag == 2) {
421 const int chi_mantissa = dspTime & 0x1FF;
422 const int chi_exponent = (dspTime >> 9) & 7;
423 const int chi2 = chi_mantissa << (chi_exponent * 2);
424 newEclDigit->
setChi(chi2);
436 if (nRead != nActiveDSPChannels) {
437 B2ERROR(
"Number of active DSP channels and number of read channels don't match (Corrupted data?)"
438 <<
LogVar(
"nRead", nRead) <<
LogVar(
"nActiveDSP", nActiveDSPChannels));
443 eclWaveformSamples.resize(nADCSamplesPerChannel);
445 for (ind = 0; ind < ECL_CHANNELS_IN_SHAPER; ind++) {
447 if (((1 << ind) & adcMask) != (1 << ind))
continue;
450 adcDataDiffWidth = 0;
451 for (indSample = 0; indSample < nADCSamplesPerChannel; indSample++) {
452 if (compressMode == 0) value = readNextCollectorWord();
454 if (indSample == 0) {
455 value = readNBits(18);
457 B2DEBUG_eclunpacker(24,
"adcDataBase = " << adcDataBase);
458 value = readNBits(5);
459 adcDataDiffWidth = value;
460 B2DEBUG_eclunpacker(24,
"adcDataDiffWidth = " << adcDataDiffWidth);
462 value = readNBits(adcDataDiffWidth);
463 B2DEBUG_eclunpacker(24,
"adcDataOffset = " << value);
464 value += adcDataBase;
467 eclWaveformSamples[indSample] = value;
471 if (nADCSamplesPerChannel > 0) {
473 cellID = m_eclMapper.getCellId(iCrate, iShaper, iChannel);
475 if (cellID > 0 || m_storeUnmapped) {
476 m_eclDsps.appendNew(cellID, eclWaveformSamples);
478 if (m_useUnpackingParameters) {
480 auto params = m_unpackingParams->get(iCrate, iShaper, iChannel);
481 if (params & ECL_OFFLINE_ADC_FIT) {
482 auto result = ECLDspUtilities::shapeFitter(cellID, eclWaveformSamples, triggerPhase0);
483 if (result.quality == 2) result.time = 0;
485 if (!newEclDigits[ind]) {
486 ECLDigit* newEclDigit = m_eclDigits.appendNew();
487 newEclDigits[ind] = newEclDigit;
489 newEclDigit->
setAmp(result.amp);
492 newEclDigit->
setChi(result.chi2);
497 if (newEclDigits[ind]) {
498 int eclDspIdx = m_eclDsps.getEntries() - 1;
499 m_relDigitToDsp.add(newEclDigitsIdx[ind], eclDspIdx);
513 if (nRead != nActiveChannelsWithADCData) {
514 B2ERROR(
"Number of channels with ADC data and "
515 "number of read channels don't match (Corrupted data?)"
516 <<
LogVar(
"active channels", nActiveChannelsWithADCData)
517 <<
LogVar(
"read channels", nRead));
526 if (m_storeTrigTime && shapersMask != 0) {
527 int trigId = iCrate & 0x3F;
528 ECLTrig* eclTrig = &m_eclTrigsBuffer[trigId - 1];
530 trigId |= (burstSuppressionMask & 0xFFF) << 6;
540 B2ERROR(
"Corrupted data from ECL collector");
547 bool ECLUnpackerModule::isDSPValid(
int cellID,
int crate,
int shaper,
int channel,
int,
int,
int quality)
550 if (cellID < 1)
return false;
552 if (m_useUnpackingParameters) {
554 auto params = m_unpackingParams->get(crate, shaper, channel);
555 if (params & ECL_DISCARD_DSP_DATA) {
556 if (params & ECL_KEEP_GOOD_DSP_DATA) {
557 if (quality == 0)
return true;
566 void ECLUnpackerModule::doEvtNumReport(
unsigned int iCrate,
int tag,
int evt_number)
568 if (!evtNumReported(iCrate)) {
569 B2ERROR(
"ECL trigger tag is inconsistent with event number."
570 <<
LogVar(
"crate", iCrate)
571 <<
LogVar(
"trigger tag", tag)
572 <<
LogVar(
"event number", evt_number));
573 m_evtNumReportedMask |= 1L << (iCrate - 1);
576 void ECLUnpackerModule::doTagsReport(
unsigned int iCrate,
int tag0,
int tag1)
578 if (!tagsReported(iCrate)) {
579 B2ERROR(
"Different trigger tags. ECL data is corrupted for whole run probably."
580 <<
LogVar(
"crate", iCrate)
581 <<
LogVar(
"trigger tag0", tag0) <<
LogVar(
"trigger tag1", tag1));
582 m_tagsReportedMask |= 1L << (iCrate - 1);
585 void ECLUnpackerModule::doPhasesReport(
unsigned int iCrate,
int phase0,
int phase1)
587 if (!phasesReported(iCrate)) {
588 B2ERROR(
"Different trigger phases. ECL data is corrupted for whole run probably."
589 <<
LogVar(
"crate", iCrate)
590 <<
LogVar(
"trigger phase0", phase0) <<
LogVar(
"trigger phase1", phase1));
591 m_phasesReportedMask |= 1L << (iCrate - 1);
594 void ECLUnpackerModule::doBadHeaderReport(
unsigned int iCrate)
596 if (!badHeaderReported(iCrate)) {
597 B2ERROR(
"Bad shaper header."
598 <<
LogVar(
"crate", iCrate));
599 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
Abstract base class for different kinds of events.