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>
22 using namespace Belle2::KLM;
29 m_triggerCTimeOfPreviousEvent(0)
31 setDescription(
"KLM unpacker (creates KLMDigits from RawKLM).");
32 setPropertyFlags(c_ParallelProcessingCertified);
33 addParam(
"outputKLMDigitsName", m_outputKLMDigitsName,
34 "Name of KLMDigit store array.",
string(
""));
35 addParam(
"WriteDigitRaws", m_WriteDigitRaws,
36 "Record raw data in dataobject format (e.g. for debugging).",
false);
37 addParam(
"WriteWrongHits", m_WriteWrongHits,
38 "Record wrong hits (e.g. for debugging).",
false);
39 addParam(
"DebugElectronicsMap", m_DebugElectronicsMap,
40 "Debug electronics map (record DAQ channel instead of strip).",
42 addParam(
"DAQChannelBKLMScintillators", m_DAQChannelBKLMScintillators,
43 "Record DAQ channel for BKLM scintillators.",
false);
44 addParam(
"DAQChannelModule", m_DAQChannelModule,
45 "Record DAQ channel for specific module.", -1);
46 addParam(
"IgnoreWrongHits", m_IgnoreWrongHits,
47 "Ignore wrong hits (i.e. no B2ERROR).",
false);
48 addParam(
"IgnoreStrip0", m_IgnoreStrip0,
49 "Ignore hits with strip = 0 (normally expected for certain firmware "
51 addParam(
"keepEvenPackages", m_keepEvenPackages,
52 "Keep packages that have even length normally indicating that "
53 "data was corrupted ",
false);
56 KLMUnpackerModule::~KLMUnpackerModule()
60 void KLMUnpackerModule::initialize()
62 m_RawKLMs.isRequired();
64 m_Digits.registerInDataStore(m_outputKLMDigitsName);
65 m_klmDigitsOutOfRange.registerInDataStore(
"KLMDigitsOutOfRange");
67 m_DigitEventInfos.registerInDataStore();
68 m_Digits.registerRelationTo(m_DigitEventInfos);
69 m_klmDigitsOutOfRange.registerRelationTo(m_DigitEventInfos);
71 if (m_WriteDigitRaws) {
72 m_klmDigitRaws.registerInDataStore();
73 m_Digits.registerRelationTo(m_klmDigitRaws);
74 m_klmDigitsOutOfRange.registerRelationTo(m_klmDigitRaws);
78 void KLMUnpackerModule::beginRun()
80 if (!m_ElectronicsMap.isValid())
81 B2FATAL(
"KLM electronics map is not available.");
82 if (!m_FEEParameters.isValid())
83 B2FATAL(
"KLM scintillator FEE parameters are not available.");
84 m_triggerCTimeOfPreviousEvent = 0;
85 m_Time->updateConstants();
88 void KLMUnpackerModule::createDigit(
91 int sector,
int layer,
int plane,
int strip,
int lastStrip)
93 KLMDigit* klmDigit = m_Digits.appendNew();
97 bool isRPC = (subdetector == KLMElementNumbers::c_BKLM) &&
98 (layer >= BKLMElementNumbers::c_FirstRPCLayer);
109 std::pair<int, double> rpcTimes =
110 m_Time->getRPCTimes(raw->getCTime(), raw->getTDC(), triggerTime);
111 klmDigit->
setTime(rpcTimes.second);
118 double time = m_Time->getScintillatorTime(
121 KLMChannelNumber channelNumber = m_ElementNumbers->channelNumber(subdetector, section, sector, layer, plane, strip);
123 m_FEEParameters->getFEEData(channelNumber);
124 if (FEEData ==
nullptr)
125 B2FATAL(
"Incomplete KLM scintillator FEE data.");
127 klmDigit->
setFitStatus(KLM::c_ScintillatorFirmwareSuccessfulFit);
129 klmDigit->
setFitStatus(KLM::c_ScintillatorFirmwareNoSignal);
140 klmDigit->
setCTime(raw->getCTime());
141 klmDigit->
setTDC(raw->getTDC());
144 void KLMUnpackerModule::unpackKLMDigit(
145 const int* rawData,
int copper,
int hslb,
int daqSubdetector,
150 &m_klmDigitRaws, &klmDigitRaw, m_WriteDigitRaws);
152 int subdetector, section, sector, layer, plane, strip;
154 std::vector<ChannelGroup> channelGroups;
155 raw.getChannelGroups(channelGroups);
158 copper, hslb + 1, raw.getLane(), raw.getAxis(), raw.getChannel());
159 bool channelFound =
false;
161 if (channelGroup.lastChannel == 0) {
164 m_ElectronicsMap->getDetectorChannel(&electronicsChannel);
165 if (detectorChannel !=
nullptr) {
168 m_ElementNumbers->channelNumberToElementNumbers(
169 *detectorChannel, &subdetector, §ion, §or, &layer, &plane,
171 channelGroup.firstStrip = strip;
172 channelGroup.lastStrip = 0;
175 if (!(m_IgnoreWrongHits || (raw.getChannel() == 0 && m_IgnoreStrip0))) {
176 if (daqSubdetector == KLMElementNumbers::c_BKLM) {
177 B2DEBUG(20,
"Channel does not exist in the KLM electronics map."
184 B2ERROR(
"Channel does not exist in the KLM electronics map."
195 if (m_DebugElectronicsMap)
202 bool firstMatchedChannel =
true;
203 for (
int channel = channelGroup.firstChannel;
204 channel <= channelGroup.lastChannel; ++channel) {
207 m_ElectronicsMap->getDetectorChannel(&electronicsChannel);
209 if (detectorChannel !=
nullptr) {
211 m_ElementNumbers->channelNumberToElementNumbers(
212 *detectorChannel, &subdetector, §ion, §or, &layer, &plane,
214 if (firstMatchedChannel) {
215 firstMatchedChannel =
false;
216 channelGroup.firstStrip = strip;
217 channelGroup.lastStrip = 0;
219 channelGroup.lastStrip = strip;
224 if (firstMatchedChannel) {
225 B2DEBUG(20,
"No matching channels exist in the KLM electronics map."
230 <<
LogVar(
"First channel", channelGroup.firstChannel)
231 <<
LogVar(
"Last channel", channelGroup.lastChannel)
232 <<
LogVar(
"Trigger bits", raw.getTriggerBits()));
238 if (!(m_WriteWrongHits || m_DebugElectronicsMap))
245 detectorChannel = m_ElectronicsMap->getDetectorChannel(&electronicsChannel);
246 if (detectorChannel ==
nullptr)
249 m_ElementNumbers->channelNumberToElementNumbers(
250 *detectorChannel, &subdetector, §ion, §or, &layer, &plane,
252 if (m_WriteWrongHits) {
255 m_klmDigitsOutOfRange.appendNew();
257 if (m_WriteDigitRaws)
261 klmDigitOutOfRange->
setLayer(layer);
263 klmDigitOutOfRange->
setPlane(plane);
264 klmDigitOutOfRange->
setStrip(strip);
265 klmDigitOutOfRange->
setCharge(raw.getCharge());
266 klmDigitOutOfRange->
setCTime(raw.getCTime());
267 klmDigitOutOfRange->
setTDC(raw.getTDC());
272 if (m_DebugElectronicsMap) {
273 if (m_DAQChannelBKLMScintillators) {
274 if ((subdetector == KLMElementNumbers::c_BKLM) &&
275 (layer < BKLMElementNumbers::c_FirstRPCLayer))
276 strip = raw.getChannel();
278 if (m_DAQChannelModule >= 0) {
280 m_ElementNumbers->moduleNumberByChannel(*detectorChannel);
281 if (klmModule == m_DAQChannelModule)
282 strip = raw.getChannel();
286 for (
const ChannelGroup& channelGroup : channelGroups) {
287 if (channelGroup.firstStrip != 0) {
288 createDigit(&raw, klmDigitRaw, klmDigitEventInfo, subdetector, section,
289 sector, layer, plane, channelGroup.firstStrip,
290 channelGroup.lastStrip);
295 void KLMUnpackerModule::convertPCIe40ToCOPPER(
int channel,
unsigned int* copper,
int* hslb)
const
297 if (channel >= 0 && channel < 16) {
298 int id = channel / 4;
299 *copper = BKLM_ID +
id + 1;
300 *hslb = channel -
id * 4;
301 }
else if (channel >= 16 && channel < 32) {
302 int id = (channel - 16) / 4;
303 *copper = EKLM_ID +
id + 1;
304 *hslb = (channel - 16) -
id * 4;
306 B2FATAL(
"The PCIe40 channel is invalid."
307 <<
LogVar(
"Channel", channel));
310 void KLMUnpackerModule::event()
316 const int hitLength = 2;
317 for (
int i = 0; i < m_RawKLMs.getEntries(); i++) {
318 if (m_RawKLMs[i]->GetNumEvents() != 1) {
319 B2ERROR(
"RawKLM a wrong number of entries (should be 1)."
320 <<
LogVar(
"RawKLM index", i)
321 <<
LogVar(
"Number of entries", m_RawKLMs[i]->GetNumEvents()));
328 for (
int j = 0; j < m_RawKLMs[i]->GetNumEntries(); j++) {
329 unsigned int copper = m_RawKLMs[i]->GetNodeID(j);
330 int hslb, subdetector;
331 m_RawKLMs[i]->GetBuffer(j);
332 for (
int channelReadoutBoard = 0; channelReadoutBoard < m_RawKLMs[i]->GetMaxNumOfCh(j); channelReadoutBoard++) {
333 if (m_RawKLMs[i]->GetMaxNumOfCh(j) == 4) {
334 hslb = channelReadoutBoard;
335 if ((copper >= EKLM_ID) && (copper <= EKLM_ID + 4))
336 subdetector = KLMElementNumbers::c_EKLM;
337 else if ((copper >= BKLM_ID) && (copper <= BKLM_ID + 4))
338 subdetector = KLMElementNumbers::c_BKLM;
341 }
else if (m_RawKLMs[i]->GetMaxNumOfCh(j) == 48) {
342 if (channelReadoutBoard >= 0 && channelReadoutBoard < 16)
343 subdetector = KLMElementNumbers::c_BKLM;
344 else if (channelReadoutBoard >= 16 && channelReadoutBoard < 32)
345 subdetector = KLMElementNumbers::c_EKLM;
348 convertPCIe40ToCOPPER(channelReadoutBoard, &copper, &hslb);
350 B2FATAL(
"The maximum number of channels per readout board is invalid."
351 <<
LogVar(
"Number of channels", m_RawKLMs[i]->GetMaxNumOfCh(j)));
354 m_DigitEventInfos.appendNew(m_RawKLMs[i], j);
356 m_triggerCTimeOfPreviousEvent);
358 int numDetNwords = m_RawKLMs[i]->GetDetectorNwords(j, channelReadoutBoard);
359 int* hslbBuffer = m_RawKLMs[i]->GetDetectorBuffer(j, channelReadoutBoard);
360 int numHits = numDetNwords / hitLength;
361 if (numDetNwords % hitLength != 1 && numDetNwords != 0) {
362 B2ERROR(
"Incorrect number of data words."
363 <<
LogVar(
"Number of data words", numDetNwords));
364 if (!m_keepEvenPackages)
367 if (numDetNwords > 0) {
372 unsigned int revo9TriggerWord =
373 (hslbBuffer[numDetNwords - 1] >> 16) & 0xFFFF;
375 unsigned int userWord = hslbBuffer[numDetNwords - 1] & 0xFFFF;
381 for (
int iHit = 0; iHit < numHits; iHit++) {
382 unpackKLMDigit(&hslbBuffer[iHit * hitLength], copper, hslb,
383 subdetector, klmDigitEventInfo);
390 void KLMUnpackerModule::endRun()
394 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.