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");
104 "exist in ECL mapping",
false);
106 "Use ECLUnpackingParameters payload",
true);
139 B2FATAL(
"ECL Unpacker: Can't initialize eclChannelMapper!");
142 B2FATAL(
"ECL Unpacker: Can't access ECLUnpackingParameters payload");
162 for (
int i = 0; i < ECL_CRATES; i++) {
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++) {
180 ECLTrig* new_ecl_trigs[ECL_CRATES] = {};
181 for (
int i = 0; i < ECL_CRATES; i++) {
187 for (
int i = 0; i <
m_eclDigits.getEntries(); i++) {
190 if (new_ecl_trigs[crate0]) {
211 B2DEBUG_eclunpacker(22,
"Reached the end of the FINESSE buffer");
212 throw Unexpected_end_of_FINESSE_buffer();
222 unsigned int val = 0;
227 B2ERROR(
"Reached the end of the FINESSE buffer while read compressed ADC data");
229 throw Unexpected_end_of_FINESSE_buffer();
243 val &= (1 << bitsToRead) - 1;
250 int iCrate, iShaper, iChannel, cellID;
253 int adcDataBase, adcDataDiffWidth;
254 int compressMode, shaperDataLength;
255 unsigned int value = 0;
256 unsigned int nRead = 0, ind = 0, indSample = 0;
257 unsigned int nActiveChannelsWithADCData, nADCSamplesPerChannel, nActiveDSPChannels;
259 int dspMask = 0, triggerTag = 0;
261 int adcMask, adcHighMask, dspTime, dspAmplitude, dspQualityFlag;
263 int burstSuppressionMask;
266 std::vector <int> eclWaveformSamples;
268 int nodeID = rawCOPPERData->
GetNodeID(n);
271 int collectorsInNode = -1;
273 bool pcie40Data =
false;
274 if (channelsCount == 4) {
276 collectorsInNode = 2;
277 }
else if (channelsCount == 48) {
279 collectorsInNode = 18;
280 if (nodeID == BECL_ID + 3) {
281 collectorsInNode = 16;
284 B2FATAL(
"The maximum number of channels per readout board is invalid."
285 <<
LogVar(
"Number of channels", channelsCount));
289 for (
int iFINESSE = 0; iFINESSE < collectorsInNode; iFINESSE++) {
304 B2DEBUG_eclunpacker(21,
"***** iEvt " <<
m_localEvtNum <<
" node " << std::hex << nodeID);
308 B2DEBUG_eclunpacker(29,
"" << std::hex << setfill(
'0') << setw(8) <<
m_bufPtr[i]);
310 B2DEBUG_eclunpacker(21,
"***** ");
317 switch (eclSubSystem) {
318 case 0 : nShapers = ECL_BARREL_SHAPERS_IN_CRATE;
break;
319 case 1 : nShapers = ECL_FWD_SHAPERS_IN_CRATE;
break;
320 case 2 : nShapers = ECL_BKW_SHAPERS_IN_CRATE;
break;
321 default : nShapers = ECL_BARREL_SHAPERS_IN_CRATE;
325 burstSuppressionMask = 0;
329 int triggerPhase0 = -1;
330 int triggerTag0 = -1;
334 shapersMask = value & 0xFFF;
335 compressMode = (value & 0xF000) >> 12;
337 B2DEBUG_eclunpacker(22,
"ShapersMask = " << std::hex << shapersMask <<
" compressMode = " << compressMode);
340 for (iShaper = 1; iShaper <= nShapers; iShaper++) {
343 int thisShaperMask = (1 << (iShaper - 1)) & shapersMask;
344 if (thisShaperMask != (1 << (iShaper - 1)))
continue;
348 shaperDataLength = value & 0xFFFF;
349 B2DEBUG_eclunpacker(22,
"iCrate = " << iCrate <<
" iShaper = " << iShaper);
350 B2DEBUG_eclunpacker(22,
"Shaper HEADER = 0x" << std::hex << value <<
" dataLength = " << std::dec << shaperDataLength);
352 if ((value & 0x00FF0000) != 0x00100000) {
354 throw Bad_ShaperDSP_header();
358 burstSuppressionMask |= ((value >> 29) & 1) << (iShaper - 1);
359 nActiveChannelsWithADCData = (value >> 24) & 0x1F;
360 nADCSamplesPerChannel = (value >> 16) & 0x7F;
361 nActiveDSPChannels = (value >> 8) & 0x1F;
362 triggerPhase = value & 0xFF;
365 if (triggerPhase0 == -1) triggerPhase0 = triggerPhase;
366 else if (triggerPhase != triggerPhase0) {
370 B2DEBUG_eclunpacker(22,
"nActiveADCChannels = " << nActiveChannelsWithADCData <<
" samples " << nADCSamplesPerChannel <<
371 " nActiveDSPChannels "
372 << nActiveDSPChannels);
376 dspMask = (value >> 16) & 0xFFFF;
377 triggerTag = value & 0xFFFF;
378 B2DEBUG_eclunpacker(22,
"DSPMASK = 0x" << std::hex << dspMask <<
" triggerTag " << std::dec << triggerTag);
380 if (triggerTag0 == -1) triggerTag0 = triggerTag;
381 else if (triggerTag != triggerTag0) {
383 triggerTag0 |= (1 << 16);
393 adcMask = value & 0xFFFF;
394 adcHighMask = (value >> 16) & 0xFFFF;
395 B2DEBUG_eclunpacker(22,
"ADCMASK = 0x" << std::hex << adcMask <<
" adcHighMask = 0x" << adcHighMask);
397 ECLDigit* newEclDigits[ECL_CHANNELS_IN_SHAPER] = {};
398 int newEclDigitsIdx[ECL_CHANNELS_IN_SHAPER] = {};
402 for (ind = 0; ind < ECL_CHANNELS_IN_SHAPER; ind++) {
404 if (((1 << ind) & dspMask) != (1 << ind))
continue;
407 dspTime = (int)(value << 2) >> 20;
408 dspQualityFlag = (value >> 30) & 0x3;
409 dspAmplitude = (value & 0x3FFFF) - 128;
414 if (!
isDSPValid(cellID, iCrate, iShaper, iChannel, dspAmplitude, dspTime, dspQualityFlag))
continue;
417 B2DEBUG_eclunpacker(23,
"New eclDigit: cid = " << cellID <<
" amp = " << dspAmplitude <<
" time = " << dspTime <<
" qflag = " <<
422 newEclDigitsIdx[ind] =
m_eclDigits.getEntries() - 1;
423 newEclDigits[ind] = newEclDigit;
425 newEclDigit->
setAmp(dspAmplitude);
427 if (dspQualityFlag == 2) {
431 const int chi_mantissa = dspTime & 0x1FF;
432 const int chi_exponent = (dspTime >> 9) & 7;
433 const int chi2 = chi_mantissa << (chi_exponent * 2);
434 newEclDigit->
setChi(chi2);
446 if (nRead != nActiveDSPChannels) {
447 B2ERROR(
"Number of active DSP channels and number of read channels don't match (Corrupted data?)"
448 <<
LogVar(
"nRead", nRead) <<
LogVar(
"nActiveDSP", nActiveDSPChannels));
453 eclWaveformSamples.resize(nADCSamplesPerChannel);
455 for (ind = 0; ind < ECL_CHANNELS_IN_SHAPER; ind++) {
457 if (((1 << ind) & adcMask) != (1 << ind))
continue;
460 adcDataDiffWidth = 0;
461 for (indSample = 0; indSample < nADCSamplesPerChannel; indSample++) {
464 if (indSample == 0) {
467 B2DEBUG_eclunpacker(24,
"adcDataBase = " << adcDataBase);
469 adcDataDiffWidth = value;
470 B2DEBUG_eclunpacker(24,
"adcDataDiffWidth = " << adcDataDiffWidth);
473 B2DEBUG_eclunpacker(24,
"adcDataOffset = " << value);
474 value += adcDataBase;
477 eclWaveformSamples[indSample] = value;
481 if (nADCSamplesPerChannel > 0) {
486 m_eclDsps.appendNew(cellID, eclWaveformSamples);
493 if (result.quality == 2) result.time = 0;
495 if (!newEclDigits[ind]) {
497 newEclDigits[ind] = newEclDigit;
499 newEclDigit->
setAmp(result.amp);
502 newEclDigit->
setChi(result.chi2);
507 if (newEclDigits[ind]) {
508 int eclDspIdx =
m_eclDsps.getEntries() - 1;
523 if (nRead != nActiveChannelsWithADCData) {
524 B2ERROR(
"Number of channels with ADC data and "
525 "number of read channels don't match (Corrupted data?)"
526 <<
LogVar(
"active channels", nActiveChannelsWithADCData)
527 <<
LogVar(
"read channels", nRead));
537 int trigId = iCrate & 0x3F;
540 trigId |= (burstSuppressionMask & 0xFFF) << 6;
550 B2ERROR(
"Corrupted data from ECL collector");
560 if (cellID < 1)
return false;
567 if (quality == 0)
return true;
579 B2ERROR(
"ECL trigger tag is inconsistent with event number."
580 <<
LogVar(
"crate", iCrate)
581 <<
LogVar(
"trigger tag", tag)
582 <<
LogVar(
"event number", evt_number));
589 B2ERROR(
"Different trigger tags. ECL data is corrupted for whole run probably."
590 <<
LogVar(
"crate", iCrate)
591 <<
LogVar(
"trigger tag0", tag0) <<
LogVar(
"trigger tag1", tag1));
598 B2ERROR(
"Different trigger phases. ECL data is corrupted for whole run probably."
599 <<
LogVar(
"crate", iCrate)
600 <<
LogVar(
"trigger phase0", phase0) <<
LogVar(
"trigger phase1", phase1));
607 B2ERROR(
"Bad shaper header."
608 <<
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 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 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
int getSubSystem(int iCrate)
Get ECL subsystem ID by given crate number: 0 – barrel, 1 – forward. 2 – backward endcap.
bool initFromDB()
Initialize channel mapper from the conditions database.
int getCellId(int iCrate, int iShaper, int iChannel)
Get CellId by given crate number, shaper position in the crate and DSP channel number in the shaper.
int getCrateID(int iCOPPERNode, int iFINESSE, bool pcie40=false)
Get crate number by given COPPER node number and FINESSE number.
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...
void add(index_type from, index_type to, weight_type weight=1.0)
Add a new element to the relation.
void clear() override
Clear all elements from the relation.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
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.
Abstract base class for different kinds of events.