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>
25#include <ecl/utility/ECLRawDataHadron.h>
31#define B2DEBUG_eclunpacker(level, msg) \
32 if (m_debugLevel >= level) {\
33 B2DEBUG(level, msg); \
103 setDescription(
"The module reads RawECL data from the DataStore and writes the ECLDigit data");
114 "exist in ECL mapping",
false);
116 "Use ECLUnpackingParameters payload",
true);
149 B2FATAL(
"ECL Unpacker: Can't initialize eclChannelMapper!");
152 B2FATAL(
"ECL Unpacker: Can't access ECLUnpackingParameters payload");
172 for (
int i = 0; i < ECL_CRATES; i++) {
178 int nRawEclEntries =
m_rawEcl.getEntries();
180 B2DEBUG_eclunpacker(22,
"Ecl unpacker event called N_RAW = " << nRawEclEntries);
182 for (
int i = 0; i < nRawEclEntries; i++) {
183 for (
int n = 0; n <
m_rawEcl[i]->GetNumEntries(); n++) {
190 ECLTrig* new_ecl_trigs[ECL_CRATES] = {};
191 for (
int i = 0; i < ECL_CRATES; i++) {
197 for (
int i = 0; i <
m_eclDigits.getEntries(); i++) {
200 if (new_ecl_trigs[crate0]) {
221 B2DEBUG_eclunpacker(22,
"Reached the end of the FINESSE buffer");
222 throw Unexpected_end_of_FINESSE_buffer();
232 unsigned int val = 0;
237 B2ERROR(
"Reached the end of the FINESSE buffer while read compressed ADC data");
239 throw Unexpected_end_of_FINESSE_buffer();
253 val &= (1 << bitsToRead) - 1;
260 int iCrate, iShaper, iChannel, cellID;
263 int adcDataBase, adcDataDiffWidth;
264 int compressMode, shaperDataLength;
265 unsigned int value = 0;
266 unsigned int nRead = 0, ind = 0, indSample = 0;
267 unsigned int nActiveChannelsWithADCData, nADCSamplesPerChannel, nActiveDSPChannels;
269 int dspMask = 0, triggerTag = 0;
271 int adcMask, adcHighMask, dspTime, dspAmplitude, dspQualityFlag;
272 int dspHadronFraction;
273 unsigned int dataFormat;
275 int burstSuppressionMask;
278 std::vector <int> eclWaveformSamples;
280 int nodeID = rawCOPPERData->
GetNodeID(n);
283 int collectorsInNode = -1;
285 bool pcie40Data =
false;
286 if (channelsCount == 4) {
288 collectorsInNode = 2;
289 }
else if (channelsCount == 48) {
291 collectorsInNode = 18;
292 if (nodeID == BECL_ID + 3) {
293 collectorsInNode = 16;
296 B2FATAL(
"The maximum number of channels per readout board is invalid."
297 <<
LogVar(
"Number of channels", channelsCount));
301 for (
int iFINESSE = 0; iFINESSE < collectorsInNode; iFINESSE++) {
311 iCrate =
m_eclMapper.getCrateID(nodeID, iFINESSE, pcie40Data);
316 B2DEBUG_eclunpacker(21,
"***** iEvt " <<
m_localEvtNum <<
" node " << std::hex << nodeID);
320 B2DEBUG_eclunpacker(29,
"" << std::hex << setfill(
'0') << setw(8) <<
m_bufPtr[i]);
322 B2DEBUG_eclunpacker(21,
"***** ");
328 int eclSubSystem =
m_eclMapper.getSubSystem(iCrate);
329 switch (eclSubSystem) {
330 case 0 : nShapers = ECL_BARREL_SHAPERS_IN_CRATE;
break;
331 case 1 : nShapers = ECL_FWD_SHAPERS_IN_CRATE;
break;
332 case 2 : nShapers = ECL_BKW_SHAPERS_IN_CRATE;
break;
333 default : nShapers = ECL_BARREL_SHAPERS_IN_CRATE;
337 burstSuppressionMask = 0;
341 int triggerPhase0 = -1;
342 int triggerTag0 = -1;
346 shapersMask = value & 0xFFF;
347 compressMode = (value & 0xF000) >> 12;
349 B2DEBUG_eclunpacker(22,
"ShapersMask = " << std::hex << shapersMask <<
" compressMode = " << compressMode);
352 for (iShaper = 1; iShaper <= nShapers; iShaper++) {
355 int thisShaperMask = (1 << (iShaper - 1)) & shapersMask;
356 if (thisShaperMask != (1 << (iShaper - 1)))
continue;
360 shaperDataLength = value & 0xFFFF;
361 B2DEBUG_eclunpacker(22,
"iCrate = " << iCrate <<
" iShaper = " << iShaper);
362 B2DEBUG_eclunpacker(22,
"Shaper HEADER = 0x" << std::hex << value <<
" dataLength = " << std::dec << shaperDataLength);
364 if ((value & 0x001F0000) != 0x00100000) {
366 throw Bad_ShaperDSP_header();
368 dataFormat = (value >> 21) & 0x7;
371 burstSuppressionMask |= ((value >> 29) & 1) << (iShaper - 1);
372 nActiveChannelsWithADCData = (value >> 24) & 0x1F;
373 nADCSamplesPerChannel = (value >> 16) & 0x7F;
374 nActiveDSPChannels = (value >> 8) & 0x1F;
375 triggerPhase = value & 0xFF;
378 if (triggerPhase0 == -1) triggerPhase0 = triggerPhase;
379 else if (triggerPhase != triggerPhase0) {
383 B2DEBUG_eclunpacker(22,
"nActiveADCChannels = " << nActiveChannelsWithADCData <<
" samples " << nADCSamplesPerChannel <<
384 " nActiveDSPChannels "
385 << nActiveDSPChannels);
389 dspMask = (value >> 16) & 0xFFFF;
390 triggerTag = value & 0xFFFF;
391 B2DEBUG_eclunpacker(22,
"DSPMASK = 0x" << std::hex << dspMask <<
" triggerTag " << std::dec << triggerTag);
393 if (triggerTag0 == -1) triggerTag0 = triggerTag;
394 else if (triggerTag != triggerTag0) {
396 triggerTag0 |= (1 << 16);
406 adcMask = value & 0xFFFF;
407 adcHighMask = (value >> 16) & 0xFFFF;
408 B2DEBUG_eclunpacker(22,
"ADCMASK = 0x" << std::hex << adcMask <<
" adcHighMask = 0x" << adcHighMask);
410 ECLDigit* newEclDigits[ECL_CHANNELS_IN_SHAPER] = {};
411 int newEclDigitsIdx[ECL_CHANNELS_IN_SHAPER] = {};
414 dspHadronFraction = 0;
416 for (ind = 0; ind < ECL_CHANNELS_IN_SHAPER; ind++) {
418 if (((1 << ind) & dspMask) != (1 << ind))
continue;
421 if ((dataFormat & 4) == 0) {
424 dspQualityFlag = (value >> 30) & 0x3;
426 dspTime = (int)(value << 2) >> 20;
428 dspAmplitude = (value & 0x3FFFF) - 128;
433 dspQualityFlag = (value >> 30) & 0x3;
443 cellID =
m_eclMapper.getCellId(iCrate, iShaper, iChannel);
445 if (!
isDSPValid(cellID, iCrate, iShaper, iChannel, dspAmplitude, dspTime, dspQualityFlag))
continue;
448 B2DEBUG_eclunpacker(23,
"New eclDigit: cid = " << cellID <<
" amp = " << dspAmplitude <<
" time = " << dspTime <<
" qflag = " <<
453 newEclDigitsIdx[ind] =
m_eclDigits.getEntries() - 1;
454 newEclDigits[ind] = newEclDigit;
456 newEclDigit->
setAmp(dspAmplitude);
460 if (dspQualityFlag == 2) {
464 const int chi_mantissa = dspTime & 0x1FF;
465 const int chi_exponent = (dspTime >> 9) & 7;
466 const int chi2 = chi_mantissa << (chi_exponent * 2);
467 newEclDigit->
setChi(chi2);
479 if (nRead != nActiveDSPChannels) {
480 B2ERROR(
"Number of active DSP channels and number of read channels don't match (Corrupted data?)"
481 <<
LogVar(
"nRead", nRead) <<
LogVar(
"nActiveDSP", nActiveDSPChannels));
486 eclWaveformSamples.resize(nADCSamplesPerChannel);
488 for (ind = 0; ind < ECL_CHANNELS_IN_SHAPER; ind++) {
490 if (((1 << ind) & adcMask) != (1 << ind))
continue;
493 adcDataDiffWidth = 0;
494 for (indSample = 0; indSample < nADCSamplesPerChannel; indSample++) {
497 if (indSample == 0) {
500 B2DEBUG_eclunpacker(24,
"adcDataBase = " << adcDataBase);
502 adcDataDiffWidth = value;
503 B2DEBUG_eclunpacker(24,
"adcDataDiffWidth = " << adcDataDiffWidth);
506 B2DEBUG_eclunpacker(24,
"adcDataOffset = " << value);
507 value += adcDataBase;
510 eclWaveformSamples[indSample] = value;
514 if (nADCSamplesPerChannel > 0) {
516 cellID =
m_eclMapper.getCellId(iCrate, iShaper, iChannel);
519 m_eclDsps.appendNew(cellID, eclWaveformSamples);
526 if (result.quality == 2) result.time = 0;
528 if (!newEclDigits[ind]) {
530 newEclDigits[ind] = newEclDigit;
532 newEclDigit->
setAmp(result.amp);
535 newEclDigit->
setChi(result.chi2);
540 if (newEclDigits[ind]) {
541 int eclDspIdx =
m_eclDsps.getEntries() - 1;
556 if (nRead != nActiveChannelsWithADCData) {
557 B2ERROR(
"Number of channels with ADC data and "
558 "number of read channels don't match (Corrupted data?)"
559 <<
LogVar(
"active channels", nActiveChannelsWithADCData)
560 <<
LogVar(
"read channels", nRead));
570 int trigId = iCrate & 0x3F;
573 trigId |= (burstSuppressionMask & 0xFFF) << 6;
583 B2ERROR(
"Corrupted data from ECL collector");
593 if (cellID < 1)
return false;
600 if (quality == 0)
return true;
612 B2ERROR(
"ECL trigger tag is inconsistent with event number."
613 <<
LogVar(
"crate", iCrate)
614 <<
LogVar(
"trigger tag", tag)
615 <<
LogVar(
"event number", evt_number));
622 B2ERROR(
"Different trigger tags. ECL data is corrupted for whole run probably."
623 <<
LogVar(
"crate", iCrate)
624 <<
LogVar(
"trigger tag0", tag0) <<
LogVar(
"trigger tag1", tag1));
631 B2ERROR(
"Different trigger phases. ECL data is corrupted for whole run probably."
632 <<
LogVar(
"crate", iCrate)
633 <<
LogVar(
"trigger phase0", phase0) <<
LogVar(
"trigger phase1", phase1));
640 B2ERROR(
"Bad shaper header."
641 <<
LogVar(
"crate", iCrate));
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 setQuality(unsigned int NewQuality)
Set Fitting Quality.
void setAmp(int Amp)
Set Fitting Amplitude.
void setTimeFit(int TimeFit)
Set Fitting Time.
void setCellId(int CellId)
Set Cell ID.
void setChi(int Chi)
Set Chi-squared.
void setPackedHadronFraction(unsigned int packed_fraction)
Set hadron fraction See ecl/utility/include/ECLRawDataHadron.h for details.
void setDataFormat(unsigned int format)
Set ShaperDSP data format.
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 Trigger Tag (crate Id)
StoreArray< RawECL > m_rawEcl
store array for RawECL
StoreArray< ECLDsp > m_eclDsps
store array for waveforms
int m_debugLevel
Cached debug level from LogSystem.
bool isDSPValid(int cellID, int crate, int shaper, int channel, int amp, int time, int quality)
Check if DSP data should be saved to datastore.
unsigned int readNBits(int bitsToRead)
read N bits from COPPER buffer (needed for reading the compressed ADC data)
bool badHeaderReported(unsigned int iCrate)
Check if the problem with bad shaper header was already reported for crate iCrate.
void doPhasesReport(unsigned int iCrate, int phase0, int phase1)
Report the problem with trigger phases and exclude the crate from further reports of this type.
ECL::ECLChannelMapper m_eclMapper
ECL channel mapper.
bool phasesReported(unsigned int iCrate)
Check if the problem with different trigger phases was already reported for crate iCrate.
ECLUnpackerModule()
constructor
virtual void initialize() override
initialize
int m_bufPos
position in the COPPER data array
bool evtNumReported(unsigned int iCrate)
Check if the problem with trg tag <-> evt number inconsistency was already reported for crate iCrate.
std::string m_eclTrigsName
name of output collection for ECLTrig
virtual void event() override
event
void doEvtNumReport(unsigned int iCrate, int tag, int evt_number)
Report the problem with inconsistency between trg tag and evt number.
long m_badHeaderReportedMask
report only once per crate about problem with shaper header
bool m_storeUnmapped
flag for whether or not to store ECLDsp data for unmapped channels
StoreArray< ECLTrig > m_eclTrigs
store array for eclTrigs data (trigger time and tag)
void readRawECLData(RawECL *rawCOPPERData, int n)
read raw data from COPPER and fill output m_eclDigits container
virtual void endRun() override
endRun
int m_bitPos
bit position for bit-by-bit data read
virtual void terminate() override
terminate
DBObjPtr< ECLChannelMap > m_unpackingParams
Run-dependent unpacking parameters for each channel.
StoreArray< ECLDigit > m_eclDigits
store array for digitized gits
RelationArray m_relDigitToTrig
ECLDigit->ECLTrig relation array.
StoreObjPtr< EventMetaData > m_eventMetaData
store objptr for EventMetaData
std::string m_eclMapperInitFileName
name of the file with correspondence between cellID and crate/shaper/channel numbers
int m_globalEvtNum
event number from EventMetaData
long m_evtNumReportedMask
report only once per crate about inconsistency between trg tag and evt number
void doTagsReport(unsigned int iCrate, int tag0, int tag1)
Report the problem with trigger tags and exclude the crate from further reports of this type.
std::string m_eclDspsName
name of output collection for ECLDsp
virtual void beginRun() override
beginRun
bool m_storeTrigTime
flag for whether or not to store collection with trigger times
unsigned int readNextCollectorWord()
read nex word from COPPER data, check if the end of data is reached
RelationArray m_relDigitToDsp
ECLDigit->ECLTrig relation array.
int m_bufLength
length of COPPER data
int m_localEvtNum
Internally counted event number.
bool tagsReported(unsigned int iCrate)
Check if the problem with different trigger tags was already reported for crate iCrate.
@ ECL_OFFLINE_ADC_FIT
Get ECLDigits from offline waveform fit.
@ ECL_DISCARD_DSP_DATA
Skip ECLDigit unpacking.
@ ECL_KEEP_GOOD_DSP_DATA
Keep ECLDigits for quality flag 0 even if ECL_DISCARD_DSP_DATA is set.
bool m_useUnpackingParameters
Use ECLUnpackingParameters payload for run-dependent unpacking.
void doBadHeaderReport(unsigned int iCrate)
Report the problem with bad shaper header and exclude the crate from further reports of this type.
std::string m_eclDigitsName
name of output collection for ECLDigits
ECLTrig m_eclTrigsBuffer[ECL::ECL_CRATES]
ECLTrigs objects before they are added to m_eclTrigs array.
long m_phasesReportedMask
report only once per crate about problem with different trg phases
unsigned int * m_bufPtr
pointer to data from COPPER
long m_tagsReportedMask
report only once per crate about problem with different trg tags
static ECLShapeFit shapeFitter(int cid, std::vector< int > adc, int ttrig, bool adjusted_timing=true)
Emulate shape fitting algorithm from ShaperDSP using algorithm from ecl/utility/src/ECLDspEmulator....
@ c_Debug
Debug: for code development.
static LogSystem & Instance()
Static method to get a reference to the LogSystem instance.
void setDescription(const std::string &description)
Sets the description of the module.
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
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.
const LogConfig & getCurrentLogConfig(const char *package=nullptr) const
Returns the current LogConfig object used by the logging system.
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
#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.
This is a set of function for packing/unpacking the data produced by the new ShaperDSP firmware that ...
int unpackTime(int time_packed)
Time unpacking (from 11 bits float to 12 bits int)
unsigned long long unpackAmplitude(unsigned long long amp_packed)
Amplitude unpacking (from 14 bits float to 18 bit int)
double unpackHadronFraction(int fraction_packed)
Hadron fraction unpacking.
Abstract base class for different kinds of events.