12 #include <klm/modules/KLMUnpacker/KLMUnpackerModule.h>
15 #include <klm/dataobjects/bklm/BKLMElementNumbers.h>
16 #include <klm/dataobjects/KLMScintillatorFirmwareFitResult.h>
17 #include <klm/rawdata/RawData.h>
20 #include <framework/logging/Logger.h>
27 using namespace Belle2::KLM;
33 m_triggerCTimeOfPreviousEvent(0),
36 setDescription(
"KLM unpacker (creates KLMDigits from RawKLM).");
37 setPropertyFlags(c_ParallelProcessingCertified);
38 addParam(
"outputKLMDigitsName", m_outputKLMDigitsName,
39 "Name of KLMDigit store array.",
string(
""));
40 addParam(
"WriteDigitRaws", m_WriteDigitRaws,
41 "Record raw data in dataobject format (e.g. for debugging).",
false);
42 addParam(
"WriteWrongHits", m_WriteWrongHits,
43 "Record wrong hits (e.g. for debugging).",
false);
44 addParam(
"DebugElectronicsMap", m_DebugElectronicsMap,
45 "Debug electronics map (record DAQ channel instead of strip).",
47 addParam(
"DAQChannelBKLMScintillators", m_DAQChannelBKLMScintillators,
48 "Record DAQ channel for BKLM scintillators.",
false);
49 addParam(
"DAQChannelModule", m_DAQChannelModule,
50 "Record DAQ channel for specific module.", -1);
51 addParam(
"IgnoreWrongHits", m_IgnoreWrongHits,
52 "Ignore wrong hits (i.e. no B2ERROR).",
false);
53 addParam(
"IgnoreStrip0", m_IgnoreStrip0,
54 "Ignore hits with strip = 0 (normally expected for certain firmware "
56 addParam(
"keepEvenPackages", m_keepEvenPackages,
57 "Keep packages that have even length normally indicating that "
58 "data was corrupted ",
false);
59 addParam(
"SciThreshold", m_scintThreshold,
60 "Scintillator strip hits with charge lower this value will be "
61 "marked as bad.",
double(140.0));
62 addParam(
"loadThresholdFromDB", m_loadThresholdFromDB,
63 "Load threshold from database (true) or not (false)",
true);
66 KLMUnpackerModule::~KLMUnpackerModule()
70 void KLMUnpackerModule::initialize()
72 m_RawKLMs.isRequired();
74 m_Digits.registerInDataStore(m_outputKLMDigitsName);
75 m_klmDigitsOutOfRange.registerInDataStore(
"KLMDigitsOutOfRange");
77 m_DigitEventInfos.registerInDataStore();
78 m_Digits.registerRelationTo(m_DigitEventInfos);
79 m_klmDigitsOutOfRange.registerRelationTo(m_DigitEventInfos);
81 if (m_WriteDigitRaws) {
82 m_klmDigitRaws.registerInDataStore();
83 m_Digits.registerRelationTo(m_klmDigitRaws);
84 m_klmDigitsOutOfRange.registerRelationTo(m_klmDigitRaws);
88 void KLMUnpackerModule::beginRun()
90 if (!m_ElectronicsMap.isValid())
91 B2FATAL(
"KLM electronics map is not available.");
92 if (!m_TimeConversion.isValid())
93 B2FATAL(
"EKLM time conversion parameters are not available.");
94 if (!m_eklmChannels.isValid())
95 B2FATAL(
"EKLM channel data are not available.");
96 if (m_loadThresholdFromDB) {
97 if (!m_bklmADCParams.isValid())
98 B2FATAL(
"BKLM ADC threshold paramenters are not available.");
99 m_scintThreshold = m_bklmADCParams->getADCThreshold();
101 m_triggerCTimeOfPreviousEvent = 0;
104 void KLMUnpackerModule::createDigit(
107 int sector,
int layer,
int plane,
int strip,
int lastStrip)
109 KLMDigit* klmDigit = m_Digits.appendNew();
111 if (m_WriteDigitRaws)
113 bool isRPC = (subdetector == KLMElementNumbers::c_BKLM) &&
114 (layer >= BKLMElementNumbers::c_FirstRPCLayer);
125 std::pair<int, double> rpcTimes =
126 m_TimeConversion->getRPCTimes(raw->getCTime(), raw->getTDC(),
128 klmDigit->
setTime(rpcTimes.second);
135 double time = m_TimeConversion->getScintillatorTime(
138 if (subdetector == KLMElementNumbers::c_BKLM) {
139 if (raw->getCharge() < m_scintThreshold)
140 klmDigit->
setFitStatus(KLM::c_ScintillatorFirmwareSuccessfulFit);
142 klmDigit->
setFitStatus(KLM::c_ScintillatorFirmwareNoSignal);
144 int stripGlobal = m_eklmElementNumbers->stripNumber(
145 section, layer, sector, plane, strip);
147 m_eklmChannels->getChannelData(stripGlobal);
148 if (channelData ==
nullptr)
149 B2FATAL(
"Incomplete EKLM channel data.");
151 klmDigit->
setFitStatus(KLM::c_ScintillatorFirmwareSuccessfulFit);
153 klmDigit->
setFitStatus(KLM::c_ScintillatorFirmwareNoSignal);
165 klmDigit->
setCTime(raw->getCTime());
166 klmDigit->
setTDC(raw->getTDC());
169 void KLMUnpackerModule::unpackKLMDigit(
170 const int* rawData,
int copper,
int hslb,
int daqSubdetector,
175 &m_klmDigitRaws, &klmDigitRaw, m_WriteDigitRaws);
176 const uint16_t* detectorChannel;
177 int subdetector, section, sector, layer, plane, strip;
179 std::vector<ChannelGroup> channelGroups;
180 raw.getChannelGroups(channelGroups);
183 copper, hslb + 1, raw.getLane(), raw.getAxis(), raw.getChannel());
184 bool channelFound =
false;
186 if (channelGroup.lastChannel == 0) {
189 m_ElectronicsMap->getDetectorChannel(&electronicsChannel);
190 if (detectorChannel !=
nullptr) {
193 m_ElementNumbers->channelNumberToElementNumbers(
194 *detectorChannel, &subdetector, §ion, §or, &layer, &plane,
196 channelGroup.firstStrip = strip;
197 channelGroup.lastStrip = 0;
200 if (!(m_IgnoreWrongHits || (raw.getChannel() == 0 && m_IgnoreStrip0))) {
201 if (daqSubdetector == KLMElementNumbers::c_BKLM) {
202 B2DEBUG(20,
"Channel does not exist in the KLM electronics map."
209 B2ERROR(
"Channel does not exist in the KLM electronics map."
220 if (m_DebugElectronicsMap)
227 bool firstMatchedChannel =
true;
228 for (
int channel = channelGroup.firstChannel;
229 channel <= channelGroup.lastChannel; ++channel) {
232 m_ElectronicsMap->getDetectorChannel(&electronicsChannel);
234 if (detectorChannel !=
nullptr) {
236 m_ElementNumbers->channelNumberToElementNumbers(
237 *detectorChannel, &subdetector, §ion, §or, &layer, &plane,
239 if (firstMatchedChannel) {
240 firstMatchedChannel =
false;
241 channelGroup.firstStrip = strip;
242 channelGroup.lastStrip = 0;
244 channelGroup.lastStrip = strip;
249 if (firstMatchedChannel) {
250 B2DEBUG(20,
"No matching channels exist in the KLM electronics map."
255 <<
LogVar(
"First channel", channelGroup.firstChannel)
256 <<
LogVar(
"Last channel", channelGroup.lastChannel)
257 <<
LogVar(
"Trigger bits", raw.getTriggerBits()));
263 if (!(m_WriteWrongHits || m_DebugElectronicsMap))
270 detectorChannel = m_ElectronicsMap->getDetectorChannel(&electronicsChannel);
271 if (detectorChannel ==
nullptr)
274 m_ElementNumbers->channelNumberToElementNumbers(
275 *detectorChannel, &subdetector, §ion, §or, &layer, &plane,
277 if (m_WriteWrongHits) {
280 m_klmDigitsOutOfRange.appendNew();
282 if (m_WriteDigitRaws)
286 klmDigitOutOfRange->
setLayer(layer);
288 klmDigitOutOfRange->
setPlane(plane);
289 klmDigitOutOfRange->
setStrip(strip);
290 klmDigitOutOfRange->
setCharge(raw.getCharge());
291 klmDigitOutOfRange->
setCTime(raw.getCTime());
292 klmDigitOutOfRange->
setTDC(raw.getTDC());
297 if (m_DebugElectronicsMap) {
298 if (m_DAQChannelBKLMScintillators) {
299 if ((subdetector == KLMElementNumbers::c_BKLM) &&
300 (layer < BKLMElementNumbers::c_FirstRPCLayer))
301 strip = raw.getChannel();
303 if (m_DAQChannelModule >= 0) {
305 m_ElementNumbers->moduleNumberByChannel(*detectorChannel);
306 if (klmModule == m_DAQChannelModule)
307 strip = raw.getChannel();
311 for (
const ChannelGroup& channelGroup : channelGroups) {
312 if (channelGroup.firstStrip != 0) {
313 createDigit(&raw, klmDigitRaw, klmDigitEventInfo, subdetector, section,
314 sector, layer, plane, channelGroup.firstStrip,
315 channelGroup.lastStrip);
320 void KLMUnpackerModule::convertPCIe40ToCOPPER(
int channel,
unsigned int* copper,
int* hslb)
const
322 if (channel >= 0 && channel < 16) {
323 int id = channel / 4;
324 *copper = BKLM_ID +
id + 1;
325 *hslb = channel -
id * 4;
326 }
else if (channel >= 16 && channel < 32) {
327 int id = (channel - 16) / 4;
328 *copper = EKLM_ID +
id + 1;
329 *hslb = (channel - 16) -
id * 4;
331 B2FATAL(
"The PCIe40 channel is invalid."
332 <<
LogVar(
"Channel", channel));
335 void KLMUnpackerModule::event()
341 const int hitLength = 2;
342 for (
int i = 0; i < m_RawKLMs.getEntries(); i++) {
343 if (m_RawKLMs[i]->GetNumEvents() != 1) {
344 B2ERROR(
"RawKLM a wrong number of entries (should be 1)."
345 <<
LogVar(
"RawKLM index", i)
346 <<
LogVar(
"Number of entries", m_RawKLMs[i]->GetNumEvents()));
353 for (
int j = 0; j < m_RawKLMs[i]->GetNumEntries(); j++) {
354 unsigned int copper = m_RawKLMs[i]->GetNodeID(j);
355 int hslb, subdetector;
356 m_RawKLMs[i]->GetBuffer(j);
357 for (
int channelReadoutBoard = 0; channelReadoutBoard < m_RawKLMs[i]->GetMaxNumOfCh(j); channelReadoutBoard++) {
358 if (m_RawKLMs[i]->GetMaxNumOfCh(j) == 4) {
359 hslb = channelReadoutBoard;
360 if ((copper >= EKLM_ID) && (copper <= EKLM_ID + 4))
361 subdetector = KLMElementNumbers::c_EKLM;
362 else if ((copper >= BKLM_ID) && (copper <= BKLM_ID + 4))
363 subdetector = KLMElementNumbers::c_BKLM;
366 }
else if (m_RawKLMs[i]->GetMaxNumOfCh(j) == 48) {
367 if (channelReadoutBoard >= 0 && channelReadoutBoard < 16)
368 subdetector = KLMElementNumbers::c_BKLM;
369 else if (channelReadoutBoard >= 16 && channelReadoutBoard < 32)
370 subdetector = KLMElementNumbers::c_EKLM;
373 convertPCIe40ToCOPPER(channelReadoutBoard, &copper, &hslb);
375 B2FATAL(
"The maximum number of channels per readout board is invalid."
376 <<
LogVar(
"Number of channels", m_RawKLMs[i]->GetMaxNumOfCh(j)));
379 m_DigitEventInfos.appendNew(m_RawKLMs[i], j);
381 m_triggerCTimeOfPreviousEvent);
383 int numDetNwords = m_RawKLMs[i]->GetDetectorNwords(j, channelReadoutBoard);
384 int* hslbBuffer = m_RawKLMs[i]->GetDetectorBuffer(j, channelReadoutBoard);
385 int numHits = numDetNwords / hitLength;
386 if (numDetNwords % hitLength != 1 && numDetNwords != 0) {
387 B2ERROR(
"Incorrect number of data words."
388 <<
LogVar(
"Number of data words", numDetNwords));
389 if (!m_keepEvenPackages)
392 if (numDetNwords > 0) {
397 unsigned int revo9TriggerWord =
398 (hslbBuffer[numDetNwords - 1] >> 16) & 0xFFFF;
400 unsigned int userWord = hslbBuffer[numDetNwords - 1] & 0xFFFF;
406 for (
int iHit = 0; iHit < numHits; iHit++) {
407 unpackKLMDigit(&hslbBuffer[iHit * hitLength], copper, hslb,
408 subdetector, klmDigitEventInfo);
415 void KLMUnpackerModule::endRun()
419 void KLMUnpackerModule::terminate()