10 #include <klm/modules/KLMUnpacker/KLMUnpackerModule.h>
13 #include <klm/dataobjects/bklm/BKLMElementNumbers.h>
14 #include <klm/dataobjects/KLMScintillatorFirmwareFitResult.h>
15 #include <klm/rawdata/RawData.h>
18 #include <framework/logging/Logger.h>
25 using namespace Belle2::KLM;
32 m_triggerCTimeOfPreviousEvent(0)
34 setDescription(
"KLM unpacker (creates KLMDigits from RawKLM).");
35 setPropertyFlags(c_ParallelProcessingCertified);
36 addParam(
"outputKLMDigitsName", m_outputKLMDigitsName,
37 "Name of KLMDigit store array.",
string(
""));
38 addParam(
"WriteDigitRaws", m_WriteDigitRaws,
39 "Record raw data in dataobject format (e.g. for debugging).",
false);
40 addParam(
"WriteWrongHits", m_WriteWrongHits,
41 "Record wrong hits (e.g. for debugging).",
false);
42 addParam(
"DebugElectronicsMap", m_DebugElectronicsMap,
43 "Debug electronics map (record DAQ channel instead of strip).",
45 addParam(
"DAQChannelBKLMScintillators", m_DAQChannelBKLMScintillators,
46 "Record DAQ channel for BKLM scintillators.",
false);
47 addParam(
"DAQChannelModule", m_DAQChannelModule,
48 "Record DAQ channel for specific module.", -1);
49 addParam(
"IgnoreWrongHits", m_IgnoreWrongHits,
50 "Ignore wrong hits (i.e. no B2ERROR).",
false);
51 addParam(
"IgnoreStrip0", m_IgnoreStrip0,
52 "Ignore hits with strip = 0 (normally expected for certain firmware "
54 addParam(
"keepEvenPackages", m_keepEvenPackages,
55 "Keep packages that have even length normally indicating that "
56 "data was corrupted ",
false);
59 KLMUnpackerModule::~KLMUnpackerModule()
63 void KLMUnpackerModule::initialize()
65 m_RawKLMs.isRequired();
67 m_Digits.registerInDataStore(m_outputKLMDigitsName);
68 m_klmDigitsOutOfRange.registerInDataStore(
"KLMDigitsOutOfRange");
70 m_DigitEventInfos.registerInDataStore();
71 m_Digits.registerRelationTo(m_DigitEventInfos);
72 m_klmDigitsOutOfRange.registerRelationTo(m_DigitEventInfos);
74 if (m_WriteDigitRaws) {
75 m_klmDigitRaws.registerInDataStore();
76 m_Digits.registerRelationTo(m_klmDigitRaws);
77 m_klmDigitsOutOfRange.registerRelationTo(m_klmDigitRaws);
81 void KLMUnpackerModule::beginRun()
83 if (!m_ElectronicsMap.isValid())
84 B2FATAL(
"KLM electronics map is not available.");
85 if (!m_FEEParameters.isValid())
86 B2FATAL(
"KLM scintillator FEE parameters are not available.");
87 m_triggerCTimeOfPreviousEvent = 0;
88 m_Time->updateConstants();
91 void KLMUnpackerModule::createDigit(
94 int sector,
int layer,
int plane,
int strip,
int lastStrip)
96 KLMDigit* klmDigit = m_Digits.appendNew();
100 bool isRPC = (subdetector == KLMElementNumbers::c_BKLM) &&
101 (layer >= BKLMElementNumbers::c_FirstRPCLayer);
112 std::pair<int, double> rpcTimes =
113 m_Time->getRPCTimes(raw->getCTime(), raw->getTDC(), triggerTime);
114 klmDigit->
setTime(rpcTimes.second);
121 double time = m_Time->getScintillatorTime(
124 KLMChannelNumber channelNumber = m_ElementNumbers->channelNumber(subdetector, section, sector, layer, plane, strip);
126 m_FEEParameters->getFEEData(channelNumber);
127 if (FEEData ==
nullptr)
128 B2FATAL(
"Incomplete KLM scintillator FEE data.");
130 klmDigit->
setFitStatus(KLM::c_ScintillatorFirmwareSuccessfulFit);
132 klmDigit->
setFitStatus(KLM::c_ScintillatorFirmwareNoSignal);
143 klmDigit->
setCTime(raw->getCTime());
144 klmDigit->
setTDC(raw->getTDC());
147 void KLMUnpackerModule::unpackKLMDigit(
148 const int* rawData,
int copper,
int hslb,
int daqSubdetector,
153 &m_klmDigitRaws, &klmDigitRaw, m_WriteDigitRaws);
155 int subdetector, section, sector, layer, plane, strip;
157 std::vector<ChannelGroup> channelGroups;
158 raw.getChannelGroups(channelGroups);
161 copper, hslb + 1, raw.getLane(), raw.getAxis(), raw.getChannel());
162 bool channelFound =
false;
164 if (channelGroup.lastChannel == 0) {
167 m_ElectronicsMap->getDetectorChannel(&electronicsChannel);
168 if (detectorChannel !=
nullptr) {
171 m_ElementNumbers->channelNumberToElementNumbers(
172 *detectorChannel, &subdetector, §ion, §or, &layer, &plane,
174 channelGroup.firstStrip = strip;
175 channelGroup.lastStrip = 0;
178 if (!(m_IgnoreWrongHits || (raw.getChannel() == 0 && m_IgnoreStrip0))) {
179 if (daqSubdetector == KLMElementNumbers::c_BKLM) {
180 B2DEBUG(20,
"Channel does not exist in the KLM electronics map."
187 B2ERROR(
"Channel does not exist in the KLM electronics map."
198 if (m_DebugElectronicsMap)
205 bool firstMatchedChannel =
true;
206 for (
int channel = channelGroup.firstChannel;
207 channel <= channelGroup.lastChannel; ++channel) {
210 m_ElectronicsMap->getDetectorChannel(&electronicsChannel);
212 if (detectorChannel !=
nullptr) {
214 m_ElementNumbers->channelNumberToElementNumbers(
215 *detectorChannel, &subdetector, §ion, §or, &layer, &plane,
217 if (firstMatchedChannel) {
218 firstMatchedChannel =
false;
219 channelGroup.firstStrip = strip;
220 channelGroup.lastStrip = 0;
222 channelGroup.lastStrip = strip;
227 if (firstMatchedChannel) {
228 B2DEBUG(20,
"No matching channels exist in the KLM electronics map."
233 <<
LogVar(
"First channel", channelGroup.firstChannel)
234 <<
LogVar(
"Last channel", channelGroup.lastChannel)
235 <<
LogVar(
"Trigger bits", raw.getTriggerBits()));
241 if (!(m_WriteWrongHits || m_DebugElectronicsMap))
248 detectorChannel = m_ElectronicsMap->getDetectorChannel(&electronicsChannel);
249 if (detectorChannel ==
nullptr)
252 m_ElementNumbers->channelNumberToElementNumbers(
253 *detectorChannel, &subdetector, §ion, §or, &layer, &plane,
255 if (m_WriteWrongHits) {
258 m_klmDigitsOutOfRange.appendNew();
260 if (m_WriteDigitRaws)
264 klmDigitOutOfRange->
setLayer(layer);
266 klmDigitOutOfRange->
setPlane(plane);
267 klmDigitOutOfRange->
setStrip(strip);
268 klmDigitOutOfRange->
setCharge(raw.getCharge());
269 klmDigitOutOfRange->
setCTime(raw.getCTime());
270 klmDigitOutOfRange->
setTDC(raw.getTDC());
275 if (m_DebugElectronicsMap) {
276 if (m_DAQChannelBKLMScintillators) {
277 if ((subdetector == KLMElementNumbers::c_BKLM) &&
278 (layer < BKLMElementNumbers::c_FirstRPCLayer))
279 strip = raw.getChannel();
281 if (m_DAQChannelModule >= 0) {
283 m_ElementNumbers->moduleNumberByChannel(*detectorChannel);
284 if (klmModule == m_DAQChannelModule)
285 strip = raw.getChannel();
289 for (
const ChannelGroup& channelGroup : channelGroups) {
290 if (channelGroup.firstStrip != 0) {
291 createDigit(&raw, klmDigitRaw, klmDigitEventInfo, subdetector, section,
292 sector, layer, plane, channelGroup.firstStrip,
293 channelGroup.lastStrip);
298 void KLMUnpackerModule::convertPCIe40ToCOPPER(
int channel,
unsigned int* copper,
int* hslb)
const
300 if (channel >= 0 && channel < 16) {
301 int id = channel / 4;
302 *copper = BKLM_ID +
id + 1;
303 *hslb = channel -
id * 4;
304 }
else if (channel >= 16 && channel < 32) {
305 int id = (channel - 16) / 4;
306 *copper = EKLM_ID +
id + 1;
307 *hslb = (channel - 16) -
id * 4;
309 B2FATAL(
"The PCIe40 channel is invalid."
310 <<
LogVar(
"Channel", channel));
313 void KLMUnpackerModule::event()
319 const int hitLength = 2;
320 for (
int i = 0; i < m_RawKLMs.getEntries(); i++) {
321 if (m_RawKLMs[i]->GetNumEvents() != 1) {
322 B2ERROR(
"RawKLM a wrong number of entries (should be 1)."
323 <<
LogVar(
"RawKLM index", i)
324 <<
LogVar(
"Number of entries", m_RawKLMs[i]->GetNumEvents()));
331 for (
int j = 0; j < m_RawKLMs[i]->GetNumEntries(); j++) {
332 unsigned int copper = m_RawKLMs[i]->GetNodeID(j);
333 int hslb, subdetector;
334 m_RawKLMs[i]->GetBuffer(j);
335 for (
int channelReadoutBoard = 0; channelReadoutBoard < m_RawKLMs[i]->GetMaxNumOfCh(j); channelReadoutBoard++) {
336 if (m_RawKLMs[i]->GetMaxNumOfCh(j) == 4) {
337 hslb = channelReadoutBoard;
338 if ((copper >= EKLM_ID) && (copper <= EKLM_ID + 4))
339 subdetector = KLMElementNumbers::c_EKLM;
340 else if ((copper >= BKLM_ID) && (copper <= BKLM_ID + 4))
341 subdetector = KLMElementNumbers::c_BKLM;
344 }
else if (m_RawKLMs[i]->GetMaxNumOfCh(j) == 48) {
345 if (channelReadoutBoard >= 0 && channelReadoutBoard < 16)
346 subdetector = KLMElementNumbers::c_BKLM;
347 else if (channelReadoutBoard >= 16 && channelReadoutBoard < 32)
348 subdetector = KLMElementNumbers::c_EKLM;
351 convertPCIe40ToCOPPER(channelReadoutBoard, &copper, &hslb);
353 B2FATAL(
"The maximum number of channels per readout board is invalid."
354 <<
LogVar(
"Number of channels", m_RawKLMs[i]->GetMaxNumOfCh(j)));
357 m_DigitEventInfos.appendNew(m_RawKLMs[i], j);
359 m_triggerCTimeOfPreviousEvent);
361 int numDetNwords = m_RawKLMs[i]->GetDetectorNwords(j, channelReadoutBoard);
362 int* hslbBuffer = m_RawKLMs[i]->GetDetectorBuffer(j, channelReadoutBoard);
363 int numHits = numDetNwords / hitLength;
364 if (numDetNwords % hitLength != 1 && numDetNwords != 0) {
365 B2ERROR(
"Incorrect number of data words."
366 <<
LogVar(
"Number of data words", numDetNwords));
367 if (!m_keepEvenPackages)
370 if (numDetNwords > 0) {
375 unsigned int revo9TriggerWord =
376 (hslbBuffer[numDetNwords - 1] >> 16) & 0xFFFF;
378 unsigned int userWord = hslbBuffer[numDetNwords - 1] & 0xFFFF;
384 for (
int iHit = 0; iHit < numHits; iHit++) {
385 unpackKLMDigit(&hslbBuffer[iHit * hitLength], copper, hslb,
386 subdetector, klmDigitEventInfo);
393 void KLMUnpackerModule::endRun()
397 void KLMUnpackerModule::terminate()
Class to store debugging informations from the unpacker (event based).
void increaseOutOfRangeHits()
Increase by 1 the number of outOfRange-flagged hits in the event.
unsigned int getTriggerCTime() const
Get trigger CTIME.
void increaseSciHits()
Increase by 1 the number of scintillator hits in the event.
void setUserWord(unsigned int userWord)
Set user word (from DCs).
void setRevo9TriggerWord(unsigned int revo9TriggerWord)
Set Revo9 trigger word (from DCs).
void setPreviousEventTriggerCTime(unsigned int triggerCTimeOfPreviousEvent)
Set trigger CTime of previous event.
unsigned int getRevo9TriggerWord() const
Get revo9 trigger word (from DCs).
void increaseRPCHits()
Increase by 1 the number of RPC hits in the event.
Class to store the raw words from the unpacker, digit-by-digit.
KLM digit (class representing a digitized hit in RPCs or scintillators).
void setLastStrip(int lastStrip)
Set last strip number (for multi-strip digits).
void setSection(int section)
Set section number.
void setCTime(uint16_t ctime)
Set CTIME.
void setStrip(int strip)
Set strip number.
void setTime(float time)
Set hit time.
void setSubdetector(int subdetector)
Set subdetector number.
void setSector(int sector)
Set sector number.
void setTDC(uint16_t tdc)
Set TDC.
void setFitStatus(int s)
Set fit status.
void setCharge(uint16_t charge)
Set charge.
void setPlane(int plane)
Set plane number.
void setLayer(int layer)
Set layer number.
BKLM electronics channel.
int getSlot() const
Get slot.
int getCopper() const
Get copper.
int getChannel() const
Get channel.
int getAxis() const
Get axis.
int getLane() const
Get lane.
void setChannel(int channel)
Set channel.
int getThreshold() const
Get threshold.
void addRelationTo(const RelationsInterface< BASE > *object, float weight=1.0, const std::string &namedRelation="") const
Add a relation from this object to another object (with caching).
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.
uint16_t KLMChannelNumber
Channel number.
uint16_t KLMModuleNumber
Module number.
Abstract base class for different kinds of events.