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]) {
213 B2DEBUG_eclunpacker(22,
"Reached the end of the FINESSE buffer");
214 throw Unexpected_end_of_FINESSE_buffer();
224 unsigned int val = 0;
229 B2ERROR(
"Reached the end of the FINESSE buffer while read compressed ADC data");
231 throw Unexpected_end_of_FINESSE_buffer();
245 val &= (1 << bitsToRead) - 1;
252 int iCrate, iShaper, iChannel, cellID;
255 int adcDataBase, adcDataDiffWidth;
256 int compressMode, shaperDataLength;
257 unsigned int value = 0;
258 unsigned int nRead = 0, ind = 0, indSample = 0;
259 unsigned int nActiveChannelsWithADCData, nADCSamplesPerChannel, nActiveDSPChannels;
261 int dspMask = 0, triggerTag = 0;
263 int adcMask, adcHighMask, dspTime, dspAmplitude, dspQualityFlag;
264 int dspHadronFraction;
265 unsigned int dataFormat;
267 int burstSuppressionMask;
270 std::vector <int> eclWaveformSamples;
272 int nodeID = rawCOPPERData->
GetNodeID(n);
275 int collectorsInNode = -1;
277 bool pcie40Data =
false;
278 if (channelsCount == 4) {
280 collectorsInNode = 2;
281 }
else if (channelsCount == 48) {
283 collectorsInNode = 18;
284 if (nodeID == BECL_ID + 3) {
285 collectorsInNode = 16;
288 B2FATAL(
"The maximum number of channels per readout board is invalid."
289 <<
LogVar(
"Number of channels", channelsCount));
293 for (
int iFINESSE = 0; iFINESSE < collectorsInNode; iFINESSE++) {
303 iCrate =
m_eclMapper.getCrateID(nodeID, iFINESSE, pcie40Data);
308 B2DEBUG_eclunpacker(21,
"***** iEvt " <<
m_localEvtNum <<
" node " << std::hex << nodeID);
312 B2DEBUG_eclunpacker(29,
"" << std::hex << setfill(
'0') << setw(8) <<
m_bufPtr[i]);
314 B2DEBUG_eclunpacker(21,
"***** ");
320 int eclSubSystem =
m_eclMapper.getSubSystem(iCrate);
321 switch (eclSubSystem) {
322 case 0 : nShapers = ECL_BARREL_SHAPERS_IN_CRATE;
break;
323 case 1 : nShapers = ECL_FWD_SHAPERS_IN_CRATE;
break;
324 case 2 : nShapers = ECL_BKW_SHAPERS_IN_CRATE;
break;
325 default : nShapers = ECL_BARREL_SHAPERS_IN_CRATE;
329 burstSuppressionMask = 0;
333 int triggerPhase0 = -1;
334 int triggerTag0 = -1;
338 shapersMask = value & 0xFFF;
339 compressMode = (value & 0xF000) >> 12;
341 B2DEBUG_eclunpacker(22,
"ShapersMask = " << std::hex << shapersMask <<
" compressMode = " << compressMode);
344 for (iShaper = 1; iShaper <= nShapers; iShaper++) {
347 int thisShaperMask = (1 << (iShaper - 1)) & shapersMask;
348 if (thisShaperMask != (1 << (iShaper - 1)))
continue;
352 shaperDataLength = value & 0xFFFF;
353 B2DEBUG_eclunpacker(22,
"iCrate = " << iCrate <<
" iShaper = " << iShaper);
354 B2DEBUG_eclunpacker(22,
"Shaper HEADER = 0x" << std::hex << value <<
" dataLength = " << std::dec << shaperDataLength);
356 if ((value & 0x001F0000) != 0x00100000) {
358 throw Bad_ShaperDSP_header();
360 dataFormat = (value >> 21) & 0x7;
363 burstSuppressionMask |= ((value >> 29) & 1) << (iShaper - 1);
364 nActiveChannelsWithADCData = (value >> 24) & 0x1F;
365 nADCSamplesPerChannel = (value >> 16) & 0x7F;
366 nActiveDSPChannels = (value >> 8) & 0x1F;
367 triggerPhase = value & 0xFF;
370 if (triggerPhase0 == -1) triggerPhase0 = triggerPhase;
371 else if (triggerPhase != triggerPhase0) {
375 B2DEBUG_eclunpacker(22,
"nActiveADCChannels = " << nActiveChannelsWithADCData <<
" samples " << nADCSamplesPerChannel <<
376 " nActiveDSPChannels "
377 << nActiveDSPChannels);
381 dspMask = (value >> 16) & 0xFFFF;
382 triggerTag = value & 0xFFFF;
383 B2DEBUG_eclunpacker(22,
"DSPMASK = 0x" << std::hex << dspMask <<
" triggerTag " << std::dec << triggerTag);
385 if (triggerTag0 == -1) triggerTag0 = triggerTag;
386 else if (triggerTag != triggerTag0) {
388 triggerTag0 |= (1 << 16);
398 adcMask = value & 0xFFFF;
399 adcHighMask = (value >> 16) & 0xFFFF;
400 B2DEBUG_eclunpacker(22,
"ADCMASK = 0x" << std::hex << adcMask <<
" adcHighMask = 0x" << adcHighMask);
402 ECLDigit* newEclDigits[ECL_CHANNELS_IN_SHAPER] = {};
403 int newEclDigitsIdx[ECL_CHANNELS_IN_SHAPER] = {};
406 dspHadronFraction = 0;
408 for (ind = 0; ind < ECL_CHANNELS_IN_SHAPER; ind++) {
410 if (((1 << ind) & dspMask) != (1 << ind))
continue;
413 if ((dataFormat & 4) == 0) {
416 dspQualityFlag = (value >> 30) & 0x3;
418 dspTime = (int)(value << 2) >> 20;
420 dspAmplitude = (value & 0x3FFFF) - 128;
425 dspQualityFlag = (value >> 30) & 0x3;
435 cellID =
m_eclMapper.getCellId(iCrate, iShaper, iChannel);
437 if (!
isDSPValid(cellID, iCrate, iShaper, iChannel, dspAmplitude, dspTime, dspQualityFlag))
continue;
440 B2DEBUG_eclunpacker(23,
"New eclDigit: cid = " << cellID <<
" amp = " << dspAmplitude <<
" time = " << dspTime <<
" qflag = " <<
445 newEclDigitsIdx[ind] =
m_eclDigits.getEntries() - 1;
446 newEclDigits[ind] = newEclDigit;
448 newEclDigit->
setAmp(dspAmplitude);
452 if (dspQualityFlag == 2) {
456 const int chi_mantissa = dspTime & 0x1FF;
457 const int chi_exponent = (dspTime >> 9) & 7;
458 const int chi2 = chi_mantissa << (chi_exponent * 2);
459 newEclDigit->
setChi(chi2);
471 if (nRead != nActiveDSPChannels) {
472 B2ERROR(
"Number of active DSP channels and number of read channels don't match (Corrupted data?)"
473 <<
LogVar(
"nRead", nRead) <<
LogVar(
"nActiveDSP", nActiveDSPChannels));
478 eclWaveformSamples.resize(nADCSamplesPerChannel);
480 for (ind = 0; ind < ECL_CHANNELS_IN_SHAPER; ind++) {
482 if (((1 << ind) & adcMask) != (1 << ind))
continue;
485 adcDataDiffWidth = 0;
486 for (indSample = 0; indSample < nADCSamplesPerChannel; indSample++) {
489 if (indSample == 0) {
492 B2DEBUG_eclunpacker(24,
"adcDataBase = " << adcDataBase);
494 adcDataDiffWidth = value;
495 B2DEBUG_eclunpacker(24,
"adcDataDiffWidth = " << adcDataDiffWidth);
498 B2DEBUG_eclunpacker(24,
"adcDataOffset = " << value);
499 value += adcDataBase;
502 eclWaveformSamples[indSample] = value;
506 if (nADCSamplesPerChannel > 0) {
508 cellID =
m_eclMapper.getCellId(iCrate, iShaper, iChannel);
511 m_eclDsps.appendNew(cellID, eclWaveformSamples);
518 if (result.quality == 2) result.time = 0;
520 if (!newEclDigits[ind]) {
522 newEclDigits[ind] = newEclDigit;
524 newEclDigit->
setAmp(result.amp);
527 newEclDigit->
setChi(result.chi2);
532 if (newEclDigits[ind]) {
533 int eclDspIdx =
m_eclDsps.getEntries() - 1;
548 if (nRead != nActiveChannelsWithADCData) {
549 B2ERROR(
"Number of channels with ADC data and "
550 "number of read channels don't match (Corrupted data?)"
551 <<
LogVar(
"active channels", nActiveChannelsWithADCData)
552 <<
LogVar(
"read channels", nRead));
562 int trigId = iCrate & 0x3F;
565 trigId |= (burstSuppressionMask & 0xFFF) << 6;
575 B2ERROR(
"Corrupted data from ECL collector");
585 if (cellID < 1)
return false;
592 if (quality == 0)
return true;
604 B2ERROR(
"ECL trigger tag is inconsistent with event number."
605 <<
LogVar(
"crate", iCrate)
606 <<
LogVar(
"trigger tag", tag)
607 <<
LogVar(
"event number", evt_number));
614 B2ERROR(
"Different trigger tags. ECL data is corrupted for whole run probably."
615 <<
LogVar(
"crate", iCrate)
616 <<
LogVar(
"trigger tag0", tag0) <<
LogVar(
"trigger tag1", tag1));
623 B2ERROR(
"Different trigger phases. ECL data is corrupted for whole run probably."
624 <<
LogVar(
"crate", iCrate)
625 <<
LogVar(
"trigger phase0", phase0) <<
LogVar(
"trigger phase1", phase1));
632 B2ERROR(
"Bad shaper header."
633 <<
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
int m_bitPos
bit position for bit-by-bit data read
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, const 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.