CbmRoot
Loading...
Searching...
No Matches
CbmMuchUnpackAlgo.cxx
Go to the documentation of this file.
1/* Copyright (C) 2022 Fair GmbH, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Pierre-Alain Loizeau [committer] */
4
5#include "CbmMuchUnpackAlgo.h"
6
7#include "CbmMuchDigi.h"
8
9#include <FairParGenericSet.h>
10#include <FairTask.h>
11#include <Logger.h>
12
13#include <Rtypes.h>
14#include <RtypesCore.h>
15
16#include <bitset>
17#include <cstdint>
18#include <iomanip>
19
20CbmMuchUnpackAlgo::CbmMuchUnpackAlgo() : CbmRecoUnpackAlgo("CbmMuchUnpackAlgo") {}
21
22CbmMuchUnpackAlgo::CbmMuchUnpackAlgo(std::string name) : CbmRecoUnpackAlgo(name) {}
23
25
26// ---- GetParContainerRequest ----
27std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>*
28 CbmMuchUnpackAlgo::GetParContainerRequest(std::string /*geoTag*/, uint32_t /*runId*/)
29{
30 // Basepath for default Much parameter sets (those connected to a geoTag)
31 std::string basepath = Form("%s", fParFilesBasePath.data());
32 std::string temppath = "";
33
34 // // Get parameter container
35 temppath = basepath + fParFileName;
36 LOG(debug) << "mMuchPar path Name: " << temppath;
37 fParContVec.emplace_back(std::make_pair(temppath, std::make_shared<CbmMuchUnpackPar>()));
38
39 return &fParContVec;
40}
41
42// ---- getAsicIndex ----
43/*
44uint32_t CbmMuchUnpackAlgo::getFebIndex(uint32_t dpbidx, uint32_t crobidx, uint16_t elinkidx)
45{
46 // This function generates FEB index between 0 to dpbidx * 9 NrAsicsPerCrob
47 uint32_t asicidx = fUnpackPar->ElinkIdxToFebIdx(elinkidx);
48 const uint32_t uAsicIdx = (dpbidx * fNrCrobPerDpb + crobidx) * fNrAsicsPerCrob + asicidx;
49 return uAsicIdx;
50}
51*/
52
53// ---- getFullTimeStamp ----
54uint64_t CbmMuchUnpackAlgo::getFullTimeStamp(const uint16_t usRawTs)
55{
56 // Use TS w/o overlap bits as they will anyway come from the TS_MSB
57 const uint64_t ulTime =
58 usRawTs + fulTsMsbIndexInTs[fuCurrDpbIdx] * static_cast<uint64_t>(stsxyter::kuHitNbTsBinsBinning);
59 /*
60 + static_cast<uint64_t>(stsxyter::kuHitNbTsBinsBinning) * static_cast<uint64_t>(fvulCurrentTsMsb[fuCurrDpbIdx])
61 + static_cast<uint64_t>(stsxyter::kulTsCycleNbBinsBinning)
62 * static_cast<uint64_t>(fvuCurrentTsMsbCycle[fuCurrDpbIdx]);
63*/
64 return ulTime;
65}
66
67// ---- init
69{
70 LOG(debug) << " Below are the list of addresses of noisy channels ";
71 for (auto it = fInactiveChannels.begin(); it != fInactiveChannels.end(); ++it)
72 LOG(debug) << " " << *it;
73
74 return kTRUE;
75}
76
77// ---- initDpbIdIndexMap ----
79{
80 fDpbIdIndexMap.clear();
81 for (uint32_t uDpb = 0; uDpb < parset->GetNrOfDpbs(); ++uDpb) {
82 fDpbIdIndexMap[parset->GetDpbId(uDpb)] = uDpb;
83 LOG(debug) << "Eq. ID for DPB #" << std::setw(2) << uDpb << " = 0x" << std::setw(4) << std::hex
84 << parset->GetDpbId(uDpb) << std::dec << " => " << fDpbIdIndexMap[parset->GetDpbId(uDpb)];
85 }
86}
87
88// ---- initParSet(FairParGenericSet* parset) ----
89Bool_t CbmMuchUnpackAlgo::initParSet(FairParGenericSet* parset)
90{
91 LOG(info) << fName << "::initParSet - for container " << parset->ClassName();
92 if (parset->IsA() == CbmMuchUnpackPar::Class()) return initParSet(static_cast<CbmMuchUnpackPar*>(parset));
93
94 // If we do not know the derived ParSet class we return false
95 LOG(error)
96 << fName << "::initParSet - for container " << parset->ClassName()
97 << " failed, since CbmMuchUnpackAlgo::initParSet() does not know the derived ParSet and what to do with it!";
98 return kFALSE;
99}
100
101// ---- initParSet(CbmMuchUnpackPar* parset) ----
103{
104 fUnpackPar = parset;
105 fUnpackPar->SetElinkFebMap2022(fbElinkFebMap2022);
106 LOG(debug) << fName << "::initParSetAsic - ";
107
108 //Type of each module: 0 for connectors on the right, 1 for connectors on the left
109 // std::vector<int32_t> viModuleType;
110
111 // STS address for the first strip of each module
112 // std::vector<int32_t> viModAddress;
113
114 // Idx of the STS module for each FEB, [ NbDpb ][ NbCrobPerDpb ][ NbFebsPerCrob ], -1 if inactive
115 //std::vector<std::vector<std::vector<int32_t>>> viFebModuleIdx;
116
117 // Array to hold the active flag for all CROBs, [ NbDpb ][ NbCrobPerDpb ]
118 std::vector<std::vector<bool>> vbCrobActiveFlag;
119
120 //STS module side for each FEB, [ NbDpb ][ NbCrobPerDpb ][ NbFebsPerCrob ], 0 = P, 1 = N, -1 if inactive
121 //std::vector<std::vector<std::vector<int32_t>>> viFebModuleSide;
122
123 // Total number of STS modules in the setup
124 //const uint32_t uNbModules = parset->GetNbOfModules();
125 //LOG(debug) << "Nr. of STS Modules: " << uNbModules;
126
127 // Total number of MuCH DPBs in system
128 const uint32_t uNbOfDpbs = parset->GetNrOfDpbs();
129 LOG(debug) << "Nr. of MuCH DPBs: " << uNbOfDpbs;
130
131 // Get Nr of Febs
132 fuNbFebs = parset->GetNrOfFebs();
133 LOG(debug) << "Nr. of FEBs: " << fuNbFebs;
134
135 // Get Nr of eLinks per CROB
137
138 // Get Nr of ASICs per CROB
140
141 // Get Nr of CROBs per DPB
143
144 // Get Number of ASICs per FEB
146
147 // Get Number of Channels per Asic
149
150 // Get Number of Channels per FEB
151 fNrChsPerFeb = parset->GetNbChanPerFeb();
152
153 // Get Number of FEBs per CROB
155
156 /*
157 for (size_t ielink = 0; ielink < fNrElinksPerCrob; ++ielink) {
158 fElinkIdxToFebIdxVec.emplace_back(parset->ElinkIdxToFebIdx(ielink));
159 fElinkIdxToAsicIdxVec.emplace_back(
160 std::make_pair(parset->ElinkIdxToAsicIdxFebA(ielink), parset->ElinkIdxToAsicIdxFebB(ielink)));
161 }*/
162
163 // Get Nr of Asics
164 const uint32_t uNbStsXyters = parset->GetNrOfFebs();
165 LOG(debug) << "Nr. of StsXyter ASICs: " << uNbStsXyters;
166
167 //Initialize temporary "per Feb" fields
168 //initTempVectors(parset, &viModuleType, &viModAddress, &viFebModuleIdx, &vbCrobActiveFlag, &viFebModuleSide);
169 //initTempVectors(parset, &vbCrobActiveFlag);
170
171 // Initialize ADC cuts for FEBs
173 for (auto cut : fdAdcCut_perFeb) {
174 fvbFebAdcCut[cut.first] = cut.second;
175 }
176 // Read dpb index map from parameter container
177 initDpbIdIndexMap(parset);
178
179 if (fvdTimeOffsetNsAsics.size() < uNbStsXyters) {
180 fvdTimeOffsetNsAsics.resize(uNbStsXyters, 0.0);
181 }
182
183 /*
184 //Initialize class-wide "per Feb" fields
185 fviFebType.resize(uNbOfDpbs);
186
187 for (uint32_t uDpb = 0; uDpb < uNbOfDpbs; ++uDpb) {
188 fviFebType[uDpb].resize(fNrCrobPerDpb);
189 for (uint32_t uCrobIdx = 0; uCrobIdx < fNrCrobPerDpb; ++uCrobIdx) {
190 fviFebType[uDpb][uCrobIdx].resize(parset->GetNbFebsPerCrob(), -1);
191 for (uint32_t uFebIdx = 0; uFebIdx < parset->GetNbFebsPerCrob(); ++uFebIdx) {
192 //fvbFebPulser.push_back(parset->IsFebPulser(uDpb, uCrobIdx, uFebIdx));
193 //fvdFebAdcGain.push_back(parset->GetFebAdcGain(uDpb, uCrobIdx, uFebIdx));
194 //fvdFebAdcOffs.push_back(parset->GetFebAdcOffset(uDpb, uCrobIdx, uFebIdx));
195
196 if (0 <= viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]
197 && static_cast<uint32_t>(viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]) < uNbModules
198 && 0 <= viFebModuleSide[uDpb][uCrobIdx][uFebIdx] && viFebModuleSide[uDpb][uCrobIdx][uFebIdx] < 2) {
199 switch (viModuleType[viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]]) {
200 case 0: // FEB-8-1 with ZIF connector on the right
201 {
202 // P side (0) has type A (0)
203 // N side (1) has type B (1)
204 fviFebType[uDpb][uCrobIdx][uFebIdx] = viFebModuleSide[uDpb][uCrobIdx][uFebIdx];
205
212 fviFebAddress.push_back(viModAddress[viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]]);
213 // + (viFebModuleSide[uDpb][uCrobIdx][uFebIdx] << 25));
214 fviFebSide.push_back(viFebModuleSide[uDpb][uCrobIdx][uFebIdx]);
215 break;
216 } // case 0: // FEB-8-1 with ZIF connector on the right
217 case 1: // FEB-8-1 with ZIF connector on the left
218 {
219 // P side (0) has type B (1)
220 // N side (1) has type A (0)
221 fviFebType[uDpb][uCrobIdx][uFebIdx] = !(viFebModuleSide[uDpb][uCrobIdx][uFebIdx]);
222
229 fviFebAddress.push_back(viModAddress[viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]]);
230 // + ((!viFebModuleSide[uDpb][uCrobIdx][uFebIdx]) << 25));
231 fviFebSide.push_back(viFebModuleSide[uDpb][uCrobIdx][uFebIdx]);
232 break;
233 } // case 1: // FEB-8-1 with ZIF connector on the left
234 default:
235 LOG(fatal) << Form("Bad module type for DPB #%02u CROB #%u FEB %02u: %d", uDpb, uCrobIdx, uFebIdx,
236 viModuleType[viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]]);
237 break;
238 }
239 } // FEB active and module index OK
240 else if (-1 == viFebModuleIdx[uDpb][uCrobIdx][uFebIdx] || -1 == viFebModuleSide[uDpb][uCrobIdx][uFebIdx]) {
241 fviFebAddress.push_back(0);
242 fviFebSide.push_back(-1);
243 } // Module index or type is set to inactive
244 else {
245 LOG(fatal) << Form("Bad module Index and/or Side for DPB #%02u CROB "
246 "#%u FEB %02u: %d %d",
247 uDpb, uCrobIdx, uFebIdx, viFebModuleIdx[uDpb][uCrobIdx][uFebIdx],
248 viFebModuleSide[uDpb][uCrobIdx][uFebIdx]);
249 } // Bad module index or type for this FEB
250 }
251 }
252 }
253*/
254
255 vbCrobActiveFlag.resize(uNbOfDpbs);
256 for (uint32_t uDpb = 0; uDpb < uNbOfDpbs; ++uDpb) {
257 vbCrobActiveFlag[uDpb].resize(fNrCrobPerDpb);
258 for (uint32_t uCrobIdx = 0; uCrobIdx < fNrCrobPerDpb; ++uCrobIdx) {
259 vbCrobActiveFlag[uDpb][uCrobIdx] = parset->IsCrobActive(uDpb, uCrobIdx);
260 }
261 }
262
263 printActiveCrobs(parset, vbCrobActiveFlag);
264 //printAddressMaps(parset, viFebModuleIdx, viFebModuleSide);
265
266 LOG(debug) << "Unpacking data in bin sorter FW mode";
267 initInternalStatus(parset);
268
269 if (fMonitor) {
270 fMonitor->Init(parset);
271 LOG(info) << fName << "::initParSet - Successfully initialized MUCH monitor";
272 }
273
274 return kTRUE;
275}
276
277// ---- initTempVectors ----
278
279//ToDo: Temporary vectors to be initialized
280
281// ---- initInternalStatus ----
283{
284
285 const uint32_t uNbOfDpbs = parset->GetNrOfDpbs();
286 const uint32_t uNbStsXyters = parset->GetNrOfAsics();
287
288 fvulCurrentTsMsb.resize(uNbOfDpbs);
289 fvuCurrentTsMsbCycle.resize(uNbOfDpbs);
290 fulTsMsbIndexInTs.resize(uNbOfDpbs);
291 for (uint32_t uDpb = 0; uDpb < uNbOfDpbs; ++uDpb) {
292 fvulCurrentTsMsb[uDpb] = 0;
293 fvuCurrentTsMsbCycle[uDpb] = 0;
294 fulTsMsbIndexInTs[uDpb] = 0;
295 }
296
297 fvvusLastTsChan.resize(uNbStsXyters);
298 fvvusLastAdcChan.resize(uNbStsXyters);
299 fvvulLastTsMsbChan.resize(uNbStsXyters);
300 for (uint32_t uAsicIdx = 0; uAsicIdx < uNbStsXyters; ++uAsicIdx) {
301 fvvusLastTsChan[uAsicIdx].resize(fNrChsPerAsic, 0);
302 fvvusLastAdcChan[uAsicIdx].resize(fNrChsPerAsic, 0);
303 fvvulLastTsMsbChan[uAsicIdx].resize(fNrChsPerAsic, 0);
304 }
305}
306
307// ---- loopMsMessages ----
308void CbmMuchUnpackAlgo::loopMsMessages(const uint8_t* msContent, const uint32_t uSize, const size_t uMsIdx)
309{
310 // If not integer number of message in input buffer, print warning/error
311 if (0 != (uSize % sizeof(stsxyter::Message))) {
312 LOG(error) << "The input microslice buffer does NOT "
313 << "contain only complete sDPB messages!";
314 }
315 // Compute the number of complete messages in the input microslice buffer
316 const uint32_t uNbMessages = (uSize - (uSize % sizeof(stsxyter::Message))) / sizeof(stsxyter::Message);
317
318 // Prepare variables for the loop on contents
319 const stsxyter::Message* pMess = reinterpret_cast<const stsxyter::Message*>(msContent);
320
321 for (uint32_t uIdx = 0; uIdx < uNbMessages; uIdx++) {
323 const stsxyter::MessType typeMess = pMess[uIdx].GetMessType();
324
325 LOG(debug2) << " Msg Idx " << std::setw(6) << uIdx << " Type " << stsxyter::Message::PrintMessType(typeMess);
326
327 if (fMonitor)
328 if (fMonitor->GetDebugMode()) {
329 fMonitor->ProcessDebugInfo(pMess[uIdx], fuCurrDpbIdx);
330 }
331
332 switch (typeMess) {
334 processHitInfo(pMess[uIdx]);
335 break;
336 }
338 processTsMsbInfo(pMess[uIdx], uIdx, uMsIdx);
339 break;
340 }
342 processEpochInfo(pMess[uIdx]);
343 if (0 < uIdx) {
344 LOG(warning) << "CbmMuchUnpackAlgo::loopMsMessages => "
345 << "EPOCH message at unexpected position in MS: message " << uIdx << " VS message 0 expected!";
346 }
347 break;
348 }
350 processStatusInfo(pMess[uIdx], uIdx);
351 break;
352 }
354 break;
355 }
357 processErrorInfo(pMess[uIdx]);
358 break;
359 }
361 break;
362 }
363 default: {
364 LOG(fatal) << "CbmMuchUnpackAlgo::loopMsMessages => "
365 << "Unknown message type, should never happen, stopping "
366 "here! Type found was: "
367 << static_cast<int>(typeMess);
368 }
369 }
370 }
371}
372
373// ---- MaskNoisyChannel ----
374void CbmMuchUnpackAlgo::MaskNoisyChannel(const uint32_t uFeb, const uint32_t uChan, const bool bMasked)
375{
376 if (false == fbUseChannelMask) {
377 fbUseChannelMask = true;
379 for (uint32_t uFebIdx = 0; uFebIdx < fuNbFebs; ++uFebIdx) {
380 fvvbMaskedChannels[uFebIdx].resize(fNrChsPerFeb, false);
381 }
382 }
383 if (uFeb < fuNbFebs && uChan < fNrChsPerFeb)
384 fvvbMaskedChannels[uFeb][uChan] = bMasked;
385 else
386 LOG(fatal) << "CbmMuchUnpackAlgo::MaskNoisyChannel => Invalid FEB "
387 "and/or CHAN index:"
388 << Form(" %u vs %u and %u vs %u", uFeb, fuNbFebs, uChan, fNrChsPerFeb);
389}
390
391
392// ---- printActiveCrobs ----
394 const std::vector<std::vector<bool>>& vbCrobActiveFlag)
395{
396 for (uint32_t uDpb = 0; uDpb < parset->GetNrOfDpbs(); ++uDpb) {
397 TString sPrintoutLine = Form("DPB #%02u CROB Active ?: ", uDpb);
398 for (uint32_t uCrobIdx = 0; uCrobIdx < fNrCrobPerDpb; ++uCrobIdx) {
399 sPrintoutLine += Form("%1u", (vbCrobActiveFlag[uDpb][uCrobIdx] == true));
400 LOG(debug) << "at function printActiveCrobs";
401 }
402 LOG(debug) << sPrintoutLine;
403 }
404}
405
406// ---- printAddressMaps ----
407//To Do: fill the body accordingly
409 const std::vector<std::vector<std::vector<int32_t>>>& /*viFebModuleIdx*/,
410 const std::vector<std::vector<std::vector<int32_t>>>& /*viFebModuleSide*/)
411{
412
413 LOG(info) << "Currently this function not printing any info for MuCh.";
414 /*
415 uint32_t uGlobalFebIdx = 0;
416 for (uint32_t uDpb = 0; uDpb < parset->GetNrOfDpbs(); ++uDpb) {
417 for (uint32_t uCrobIdx = 0; uCrobIdx < fNrCrobPerDpb; ++uCrobIdx) {
418 LOG(debug) << Form("DPB #%02u CROB #%u: ", uDpb, uCrobIdx);
419 for (uint32_t uFebIdx = 0; uFebIdx < parset->GetNbFebsPerCrob(); ++uFebIdx) {
420 if (0 <= viFebModuleIdx[uDpb][uCrobIdx][uFebIdx])
421 LOG(debug) << Form(" FEB #%02u (%02u): Mod. Idx = %03d Side %c (%2d) Type %c "
422 "(%2d) (Addr. 0x%08x) ADC gain %4.0f e- ADC Offs %5.0f e-",
423 uFebIdx, uGlobalFebIdx, viFebModuleIdx[uDpb][uCrobIdx][uFebIdx],
424 1 == viFebModuleSide[uDpb][uCrobIdx][uFebIdx] ? 'N' : 'P',
425 viFebModuleSide[uDpb][uCrobIdx][uFebIdx],
426 1 == fviFebType[uDpb][uCrobIdx][uFebIdx] ? 'B' : 'A', fviFebType[uDpb][uCrobIdx][uFebIdx],
427 fviFebAddress[uGlobalFebIdx], fvdFebAdcGain[uGlobalFebIdx], fvdFebAdcOffs[uGlobalFebIdx]);
428 else
429 LOG(debug) << Form("Disabled FEB #%02u (%02u): Mod. Idx = %03d Side %c (%2d) Type %c "
430 "(%2d) (Addr. 0x%08x) ADC gain %4.0f e- ADC Offs %5.0f e-",
431 uFebIdx, uGlobalFebIdx, viFebModuleIdx[uDpb][uCrobIdx][uFebIdx],
432 1 == viFebModuleSide[uDpb][uCrobIdx][uFebIdx] ? 'N' : 'P',
433 viFebModuleSide[uDpb][uCrobIdx][uFebIdx],
434 1 == fviFebType[uDpb][uCrobIdx][uFebIdx] ? 'B' : 'A', fviFebType[uDpb][uCrobIdx][uFebIdx],
435 fviFebAddress[uGlobalFebIdx], fvdFebAdcGain[uGlobalFebIdx], fvdFebAdcOffs[uGlobalFebIdx]);
436 uGlobalFebIdx++;
437 }
438 }
439 }
440*/
441}
442
443// -------------------------------------------------------------------------
445{
446 if (mess.IsMsErrorFlagOn()) {
447 // I do pass here the Ts start time instead of the ms time, since, we removed the ms time as member for the time being
448 if (fMonitor) {
449 fMonitor->FillMsErrorsEvo(fMsStartTime, mess.GetMsErrorType());
450 }
451 if (fOptOutBVec)
452 fOptOutBVec->emplace_back(
454 }
455}
456
457// ---- processHitInfo ----
459{
460 const uint16_t usElinkIdx = mess.GetLinkIndexHitBinning();
461 // const uint32_t uCrobIdx = usElinkIdx / fNrElinksPerCrob;
462 // Get the asic index
463 //uint32_t uAsicIdx = getFebIndex(fuCurrDpbIdx, uCrobIdx, usElinkIdx);
464 //Below will generate asicidx from 0 to 8. According to Elink Number.
465 uint32_t asicidx = fUnpackPar->ElinkIdxToFebIdx(usElinkIdx);
466 //Below will generate uAsicIdx from 0 to maximum number of FEBs.
467 uint32_t uAsicIdx = fuCurrDpbIdx * fUnpackPar->GetNbFebsPerDpb() + asicidx;
468 //Below will generate FEB Position Number according to GEM and RPC.
469 int32_t uFebIdx = fUnpackPar->GetFebId(uAsicIdx);
470 if (-1 == uFebIdx) {
471 LOG(warning) << "CbmMuchUnpackAlgo::processHitInfo => "
472 << "Particular FEB is not connected. Digi is not created for this hit. Check FEB number " << uAsicIdx
473 << " generate FEB Position " << uFebIdx;
475 return;
476 }
477 if (-2 == uFebIdx) {
478 LOG(error) << "CbmMuchUnpackAlgo::processHitInfo => "
479 << "Wrong Elink Idx! "
480 << " Feb " << uFebIdx << " Elink " << usElinkIdx;
482 return;
483 }
484 const uint16_t usChan = mess.GetHitChannel();
485 const uint16_t usRawAdc = mess.GetHitAdc();
486 const uint16_t usRawTs = mess.GetHitTimeBinning();
487 const uint32_t uChanInFeb = usChan + fNrChsPerAsic * (uAsicIdx % fNrAsicsPerFeb);
488
489 // Compute the Full time stamp
490 const uint64_t ulHitTime = getFullTimeStamp(usRawTs);
491
492 //uFebIdx += ( fuCurrDpbIdx * fNrCrobPerDpb + ____CrobIndexCalculationIfNeeded___() ) * fuNbFebsPerCrob;
493 //uncomment below line if kuNbCrobsPerDpb > 1
494 //uFebIdx += (fuCurrDpbIdx * fNrCrobPerDpb) * fNrFebsPerCrob; //no Crob index calculation for now
495
496
497 if (fMonitor) fMonitor->CountRawHit(uFebIdx, uChanInFeb);
498
500 if (fvbFebAdcCut[uFebIdx] < usRawAdc) {
503 if (false == fbUseChannelMask || false == fvvbMaskedChannels[uFebIdx][uChanInFeb]) {
504
507 if (usRawTs == fvvusLastTsChan[uAsicIdx][usChan]
508 && (fbDupliWithoutAdc || usRawAdc == fvvusLastAdcChan[uAsicIdx][usChan])
509 && fulTsMsbIndexInTs[fuCurrDpbIdx] == fvvulLastTsMsbChan[uAsicIdx][usChan]) {
511 LOG(debug1) << "CbmMuchUnpackAlgo::processHitInfo => "
512 << Form("Rejecting duplicate on Asic %3u channel %3u, TS %3u, ADC %2u", uAsicIdx, usChan, usRawTs,
513 usRawAdc);
514
515 if (fMonitor) fMonitor->FillDuplicateHitsAdc(uAsicIdx, uChanInFeb, usRawAdc);
516 return;
517 } // if same TS, (ADC,) TS MSB, TS MSB cycle, reject
518 fvvusLastTsChan[uAsicIdx][usChan] = usRawTs;
519 fvvusLastAdcChan[uAsicIdx][usChan] = usRawAdc;
521 } // if (fbRejectDuplicateDigis)
522
523 //uint32_t uChanInMod = usChan + fNrChsPerAsic * (uAsicIdx % fNrAsicsPerFeb);
524
528
529 //if (0 == fviFebSide[uFebIdx])
530 // uChanInMod = fNrChsPerFeb - uChanInMod - 1 // Invert channel order
531 // + fNrChsPerFeb; // Offset for P (back) side
532
533 const double_t tsreltime = static_cast<double_t>(ulHitTime) * stsxyter::kdClockCycleNs;
534 double dTimeInNs = tsreltime - fSystemTimeOffset;
535 if (uAsicIdx < fvdTimeOffsetNsAsics.size()) dTimeInNs -= fvdTimeOffsetNsAsics[uAsicIdx];
536
537 const uint64_t ulTimeInNs = static_cast<uint64_t>(dTimeInNs);
538 //const double dCalAdc = fvdFebAdcOffs[uFebIdx] + (usRawAdc - 1) * fvdFebAdcGain[uFebIdx];
539
540 //if (0 == fviFebAddress[uFebIdx] || -1 == fviFebSide[uFebIdx]) {
541 // LOG(error) << Form("Digi on disabled FEB %02u has address 0x%08x and side %d", uFebIdx, fviFebAddress[uFebIdx],
542 // fviFebSide[uFebIdx]);
543 //}
544
545 if (fMonitor) fMonitor->CountDigi(uAsicIdx, uChanInFeb);
546 //Checking for Raw channel value
547 if (usChan > 127) LOG(debug) << "ERROR !!! Channel in hit message is out of range " << usChan;
548 // uFebIdx is FEB position in the GEM and RPC
549 const uint32_t address = CreateMuchAddress(fuCurrDpbIdx, uFebIdx, usChan);
550
551 // Masking Noisy Channel. If Address is part of Inactive Channel List
552 if (fInactiveChannels.count(address)) {
553 //Counting number of hits fall on noisy channel
555 return;
556 }
557
558
559 //const uint32_t address = CreateMuchAddress(fuCurrDpbIdx, uFebIdx, uChanInFeb);
560 LOG(debug) << "Created Much Address = " << address << " from fuCurrDpbIdx " << fuCurrDpbIdx << " Feb Id "
561 << uFebIdx << " Channnel Id " << uChanInFeb;
562 if (address) {
564 // Storing Pulser FEB Data in another output stream (pulser feb gives -7 )
565 if (-7 == uFebIdx) {
566 //presently for Pulser Output CbmMuchDigi address is 0
567 fOptOutAVec->emplace_back(CbmMuchDigi(address, usRawAdc, ulTimeInNs));
568 return;
569 } // if (-7 == uFebIdx)
570 fOutputVec.emplace_back(CbmMuchDigi(address, usRawAdc, ulTimeInNs));
571 }
572 else {
573 if (-7 != uFebIdx) { //
574 LOG(warning) << "Digi not created due to generated address is " << address;
575 }
577 }
579 //Commented below 6 lines as we do not use FebPulser Vector
580 //if (fvbFebPulser[uFebIdx]) {
581 // if (fOptOutAVec) {
582 // fOptOutAVec->emplace_back(CbmMuchDigi(address, usRawAdc, ulTimeInNs));
583 // } // if (fOptOutAVec)
584 // } // if (fvbFebPulser[uFebIdx])
585 //else {
586 // fOutputVec.emplace_back(CbmMuchDigi(address, usRawAdc, ulTimeInNs));
587 //} // else of if (fvbFebPulser[uFebIdx])
588
590 if (mess.IsHitMissedEvts())
591 if (fOptOutBVec)
592 fOptOutBVec->emplace_back(
593 CbmErrorMessage(ECbmModuleId::kMuch, dTimeInNs, uAsicIdx, 1 << stsxyter::kusLenStatStatus, usChan));
594 }
595 }
596
597 if (fMonitor) {
598 // Convert the Hit time in bins within the TS to Hit time in secondes within Unix frame (UTC or TAI)
599 const double dHitTimeAbsSec =
600 (static_cast<double_t>(ulHitTime) * stsxyter::kdClockCycleNs - fSystemTimeOffset + fTsStartTime) * 1e-9;
601
602 // Prepare monitoring values
603 const uint32_t uAsicInFeb = uAsicIdx % fNrAsicsPerFeb;
604 const double dCalAdc = usRawAdc;
605 // const double dCalAdc = fvdFebAdcOffs[uFebIdx] + (usRawAdc - 1) * fvdFebAdcGain[uFebIdx];
606
607 fMonitor->FillHitMonitoringHistos(uFebIdx, usChan, uChanInFeb, usRawAdc, dCalAdc, usRawTs, mess.IsHitMissedEvts());
608 fMonitor->FillHitEvoMonitoringHistos(uFebIdx, uAsicIdx, uAsicInFeb, uChanInFeb, dHitTimeAbsSec,
609 mess.IsHitMissedEvts());
610
611 if (fMonitor->GetDebugMode()) {
612 fMonitor->FillHitDebugMonitoringHistos(uAsicIdx, usChan, usRawAdc, usRawTs, mess.IsHitMissedEvts());
613 }
614 }
615}
616
617//---------------CreateMuchDigi -------
618//To do address need to be checked carefully
619uint32_t CbmMuchUnpackAlgo::CreateMuchAddress(uint32_t dpbidx, int32_t iFebId, uint32_t usChan)
620{
621 // For generating Station number (GEM1 station = 0, GEM2 station = 1 and RPC station = 2)
623 int32_t station = -1;
624 int32_t layer = -1;
625 if (iFebId == -7) //Pulser FEB
626 {
627 station = 6; // for Pulser
628 layer = 0; //
629 }
630 else if (dpbidx == 0 || dpbidx == 1 || dpbidx == 2) //First 3 DPBs are for GEM-1
631 {
632 station = 0; // for mCBM setup
633 layer = 0; // Station 0 for GEM-A and station 1 for Module GEM-B
634 }
635 else if (dpbidx == 4 || dpbidx == 5 || dpbidx == 6) //Last 3 DPBs are for GEM-2 after 10/04/2022
636 {
637 station = 1; // for mCBM setup station
638 layer = 0; // 0 for Module GEM-A and 1 for Module GEM-B
639 }
640 else if (dpbidx == 3) {
641 station = 2; // for mCBM setup only one station
642 layer = 0; //
643 }
644 else {
645 LOG(warning) << "Wrong DPB Id x " << dpbidx;
646 return 0;
647 } //No address generated.
648 //Common layer side module will be 0 only for mCBM 2022
649 int32_t layerside = 0; // 0 in mCBM
650 int32_t sModule = 0; // 0 in mCBM
651
652 int32_t sSector = -9; //channel values are from 0-96 therefore as per CbmMuchAddress it is sector
653 int32_t sChannel = -9; //sector values are from 0-22 therefore as per CbmMuchAddress it is channel
654
655 //Int_t usChan = itHitIn->GetChan();
656
657 // ----------------------------- //
658 // Channel flip in stsXYTER v2.1 : 0<->1, 2<->3, 3<->4 and so on...
659 auto fiFlag = 1;
660 if (fiFlag == 1) {
661 if (usChan % 2 == 0)
662 usChan = usChan + 1;
663 else
664 usChan = usChan - 1;
665 }
666 // ---------------------------- //
667 // auto iFebId = >GetFebId(febId);
668 // ---------------------------- //
669 // PadX means CHANNEL for CbmMuchAddress
670 // PadY means SECTOR for CbmMuchAddress
671 //Due to two FLEX cable connected to single FEB; First Flex Connector number 1 - 63 and second flex connector number 64 - 127
672 //in few FEB positioned these flex connectors are flipped so below correction applied.
673 if (station == 0 && fiFlag == 1 && layer == 0) { // First layer (GEM1) has old readout PCB
674 if (iFebId == 0 || iFebId == 1 || iFebId == 2 || iFebId == 3 || iFebId == 4 || iFebId == 8 || iFebId == 9
675 || iFebId == 10 || iFebId == 11 || iFebId == 17) {
676 sChannel = fUnpackPar->GetPadXA(iFebId, 127 - usChan);
677 sSector = fUnpackPar->GetPadYA(iFebId, 127 - usChan);
678 }
679 else {
680 sChannel = fUnpackPar->GetPadXA(iFebId, usChan);
681 sSector = fUnpackPar->GetPadYA(iFebId, usChan);
682 }
683 } // if( fiFlag == 1 && layer == 0 )
684 else if (station == 1 && fiFlag == 1 && layer == 0) { // second layer (GEM2) has new readout PCB
685 if (iFebId == 0 || iFebId == 1 || iFebId == 2 || iFebId == 3 || iFebId == 4 || iFebId == 8 || iFebId == 9
686 || iFebId == 10 || iFebId == 11 || iFebId == 17) {
687 sChannel = fUnpackPar->GetPadXB(iFebId, 127 - usChan);
688 sSector = fUnpackPar->GetPadYB(iFebId, 127 - usChan);
689 }
690 else {
691 sChannel = fUnpackPar->GetPadXB(iFebId, usChan);
692 sSector = fUnpackPar->GetPadYB(iFebId, usChan);
693 }
694 } // else if( fiFlag == 1 && layer == 1 )
695 else if (station == 0 || station == 1) { // Both layer with same type of PCB (Probably below is not necessary)
696 if (iFebId == 0 || iFebId == 1 || iFebId == 2 || iFebId == 3 || iFebId == 4 || iFebId == 8 || iFebId == 9
697 || iFebId == 10 || iFebId == 11 || iFebId == 17) {
698 sChannel = fUnpackPar->GetPadXA(iFebId, 127 - usChan);
699 sSector = fUnpackPar->GetPadYA(iFebId, 127 - usChan);
700 }
701 else {
702 sChannel = fUnpackPar->GetPadXA(iFebId, usChan);
703 sSector = fUnpackPar->GetPadYA(iFebId, usChan);
704 }
705 } // else{
706 else if (station == 2) { //For RPC
707 sChannel = fUnpackPar->GetPadXRpc(iFebId, usChan);
708 sSector = fUnpackPar->GetPadYRpc(iFebId, usChan);
709 }
710 else // Checking for the not connected or misconnected pads
711 {
712 LOG(debug) << "Sector " << sSector << " channel " << sChannel << " is not connected or misconnected to pad. "
713 << " corresponding Feb is " << iFebId << " and uschan " << usChan << " DPB id " << dpbidx
714 << " Skipping this hit message.";
715 return 0;
716 }
717 //Creating Unique address of the particular channel of GEM
718 //UInt_t address = CbmMuchAddress::GetAddress(station, layer, layerside, sModule, sChannel, sSector);
719 uint32_t address = CbmMuchAddress::GetAddress(station, layer, layerside, sModule, sSector, sChannel);
720 LOG(debug) << "Raw address " << address;
721 address = CbmMuchAddress::SetElementId(address, 1, station);
722 LOG(debug) << "After adding station " << address << " binary " << std::bitset<32>(address);
723 address = CbmMuchAddress::SetElementId(address, 2, layer);
724 LOG(debug) << "After adding Layer " << address << " binary " << std::bitset<32>(address);
725 address = CbmMuchAddress::SetElementId(address, 3, layerside);
726 LOG(debug) << "After adding Layer Side " << address << " binary " << std::bitset<32>(address);
727 address = CbmMuchAddress::SetElementId(address, 4, sModule);
728 LOG(debug) << "After adding module " << address << " binary " << std::bitset<32>(address);
729 address = CbmMuchAddress::SetElementId(address, 5, sSector);
730 LOG(debug) << "After adding sector " << address << " binary " << std::bitset<32>(address);
731 address = CbmMuchAddress::SetElementId(address, 6, sChannel);
732 LOG(debug) << "After adding channel " << address << " binary " << std::bitset<32>(address);
733 /*
734 Double_t dTimeInNs = itHitIn->GetTs() * stsxyter::kdClockCycleNs - fdTimeOffsetNs;
735 if (uAsicIdx < fvdTimeOffsetNsAsics.size()) dTimeInNs -= fvdTimeOffsetNsAsics[uAsicIdx];
736 ULong64_t ulTimeInNs = static_cast<ULong64_t>(dTimeInNs);
737
739 // fDigiVect.push_back( CbmMuchDigi( address, itHitIn->GetAdc(), ulTimeInNs ) );
740
742
743 CbmMuchBeamTimeDigi* digi = new CbmMuchBeamTimeDigi(address, itHitIn->GetAdc(), ulTimeInNs);
744 LOG(debug) << "Sector " << sSector << " channel " << sChannel << " layer " << layer << " Address " << address
745 << " Time " << ulTimeInNs;
746
747 digi->SetPadX(sSector);
748 digi->SetPadY(sChannel);
749 digi->SetRocId(itHitIn->GetDpb());
750 digi->SetNxId(itHitIn->GetAsic());
751 digi->SetNxCh(itHitIn->GetChan()); */
752 // Add Elink also in the stsxyter::FinalHit as one more variable such that may be used.
753 //digi.SetElink(itHitIn->GetElink());
754
755 return address;
756}
757
758//----------------------------------
759
760// ---- processStatusInfo ----
762{
763 // again fMonitor settings used for debugging printouts, I would propose to separate this
764 if (fMonitor)
765 if (fMonitor->GetDebugMode()) {
766 std::cout << Form("DPB %2u TS %12lu mess %5u ", fuCurrDpbIdx, fTsIndex, uIdx);
768 }
769
770 const uint16_t usElinkIdx = mess.GetStatusLink();
771 // const uint32_t uCrobIdx = usElinkIdx / fNrElinksPerCrob;
772 const int32_t uFebIdx = fElinkIdxToFebIdxVec.at(usElinkIdx);
773 if (-1 == uFebIdx) {
774 LOG(warning) << "CbmMuchUnpackAlgo::processStatusInfo => "
775 << "Wrong elink Idx! Elink raw " << Form("%d remap %d", usElinkIdx, uFebIdx);
776 return;
777 }
778 //const uint32_t uAsicIdx = getFebIndex(fuCurrDpbIdx, uCrobIdx, usElinkIdx);
779 //Below will generate asicidx from 0 to 8. According to Elink Number.
780 uint32_t asicidx = fUnpackPar->ElinkIdxToFebIdx(usElinkIdx);
781 //Below will generate uAsicIdx from 0 to maximum number of FEBs.
782 uint32_t uAsicIdx = fuCurrDpbIdx * fUnpackPar->GetNbFebsPerDpb() + asicidx;
783 //Below will generate FEB Position Number according to GEM and RPC.
784 //int32_t uFebIdx = fUnpackPar->GetFebId(uAsicIdx);
785 if (fMonitor) {
786 const uint16_t usStatusField = mess.GetStatusStatus();
787 fMonitor->FillMuchStatusMessType(uAsicIdx, usStatusField);
788 }
790 const int64_t ulTime = getFullTimeStamp(0);
791
793 const double dTimeNs = ulTime * stsxyter::kdClockCycleNs;
794 if (fOptOutBVec)
795 fOptOutBVec->emplace_back(
796 CbmErrorMessage(ECbmModuleId::kMuch, dTimeNs, uAsicIdx, mess.GetStatusStatus(), mess.GetData()));
797}
798
799
800// ---- processTsMsbInfo ----
801void CbmMuchUnpackAlgo::processTsMsbInfo(const stsxyter::Message& mess, uint32_t uMessIdx, uint32_t uMsIdx)
802{
803 const uint32_t uVal = mess.GetTsMsbValBinning();
804
805 // Update Status counters
806 if (uVal < fvulCurrentTsMsb[fuCurrDpbIdx]) {
807
808 LOG(debug) << " TS " << std::setw(12) << fTsIndex << " MS Idx " << std::setw(4) << uMsIdx << " Msg Idx "
809 << std::setw(5) << uMessIdx << " DPB " << std::setw(2) << fuCurrDpbIdx << " Old TsMsb " << std::setw(5)
810 << fvulCurrentTsMsb[fuCurrDpbIdx] << " Old MsbCy " << std::setw(5) << fvuCurrentTsMsbCycle[fuCurrDpbIdx]
811 << " new TsMsb " << std::setw(5) << uVal;
812
814 }
815 if (uVal != fvulCurrentTsMsb[fuCurrDpbIdx] + 1
819 && !(1 == uMessIdx && 0 == uMsIdx)
821 && !(uVal == fvulCurrentTsMsb[fuCurrDpbIdx] && 2 == uMessIdx)
823 && uVal < fvulCurrentTsMsb[fuCurrDpbIdx]) {
824 LOG(debug) << "TS MSB Jump in "
825 << " TS " << std::setw(12) << fTsIndex << " MS Idx " << std::setw(4) << uMsIdx << " Msg Idx "
826 << std::setw(5) << uMessIdx << " DPB " << std::setw(2) << fuCurrDpbIdx << " => Old TsMsb "
827 << std::setw(5) << fvulCurrentTsMsb[fuCurrDpbIdx] << " new TsMsb " << std::setw(5) << uVal;
828 }
829
831
832 LOG(debug1) << " TS " << std::setw(12) << fTsIndex << " MS Idx " << std::setw(4) << uMsIdx << " Msg Idx "
833 << std::setw(5) << uMessIdx << " DPB " << std::setw(2) << fuCurrDpbIdx << " TsMsb " << std::setw(5)
834 << fvulCurrentTsMsb[fuCurrDpbIdx] << " MsbCy " << std::setw(5) << fvuCurrentTsMsbCycle[fuCurrDpbIdx];
835
838 + (fvuCurrentTsMsbCycle[fuCurrDpbIdx] * static_cast<uint64_t>(1 << stsxyter::kusLenTsMsbValBinning));
840 LOG(fatal) << "CbmMuchUnpackAlgo::processTsMsbInfo => "
841 << "Value computed from TS_MSB and TS_MSB cycle smaller than Timeslice start in TS_MSB, "
842 << "would lead to a negative value so it cannot be recovered!!!!"
843 << std::endl
845 << "TS_MSB: " << fvulCurrentTsMsb[fuCurrDpbIdx] << " Cycle: " << fvuCurrentTsMsbCycle[fuCurrDpbIdx]
846 << " Full TS_MSB: " << fulTsMsbIndexInTs[fuCurrDpbIdx] << " TS Start offset: " << fulTsStartInTsMsb;
847 }
849
850 if (fMonitor)
851 if (fMonitor->GetDebugMode()) { //also if( 1 < uMessIdx )?
852 fMonitor->FillMuchDpbRawTsMsb(fuCurrDpbIdx, fvulCurrentTsMsb[fuCurrDpbIdx]);
853 fMonitor->FillMuchDpbRawTsMsbSx(fuCurrDpbIdx, fvulCurrentTsMsb[fuCurrDpbIdx]);
854 fMonitor->FillMuchDpbRawTsMsbDpb(fuCurrDpbIdx, fvulCurrentTsMsb[fuCurrDpbIdx]);
855 }
856}
857
858// ---- refreshTsMsbFields ----
859void CbmMuchUnpackAlgo::refreshTsMsbFields(const uint32_t imslice, const size_t mstime)
860{
861 const uint32_t uTsMsbCycleHeader =
863 const uint32_t uTsMsbHeader =
864 std::floor((mstime - uTsMsbCycleHeader * (stsxyter::kulTsCycleNbBinsBinning * stsxyter::kdClockCycleNs))
866
867 LOG(debug1) << " TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << mstime << " MS Idx " << std::setw(4)
868 << imslice << " Msg Idx " << std::setw(5) << 0 << " DPB " << std::setw(2) << fuCurrDpbIdx << " Old TsMsb "
869 << std::setw(5) << fvulCurrentTsMsb[fuCurrDpbIdx] << " Old MsbCy " << std::setw(5)
870 << fvuCurrentTsMsbCycle[fuCurrDpbIdx] << " header TsMsb " << uTsMsbHeader << " New MsbCy "
871 << uTsMsbCycleHeader;
872
873 if (0 == imslice) {
874 if (uTsMsbCycleHeader != fvuCurrentTsMsbCycle[fuCurrDpbIdx])
875 LOG(debug) << " TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << mstime << " MS Idx "
876 << std::setw(4) << imslice << " Msg Idx " << std::setw(5) << 0 << " DPB " << std::setw(2)
877 << fuCurrDpbIdx << " Old TsMsb " << std::setw(5) << fvulCurrentTsMsb[fuCurrDpbIdx] << " Old MsbCy "
878 << std::setw(5) << fvuCurrentTsMsbCycle[fuCurrDpbIdx] << " New TsMsb " << uTsMsbHeader << " New MsbCy "
879 << uTsMsbCycleHeader;
880 fvuCurrentTsMsbCycle[fuCurrDpbIdx] = uTsMsbCycleHeader;
881 fvulCurrentTsMsb[fuCurrDpbIdx] = uTsMsbHeader;
882
885 + (fvuCurrentTsMsbCycle[fuCurrDpbIdx] * static_cast<uint64_t>(1 << stsxyter::kusLenTsMsbValBinning));
887 LOG(fatal) << "CbmMuchUnpackAlgo::refreshTsMsbFields => "
888 << "Value computed from TS_MSB and TS_MSB cycle smaller than Timeslice start in TS_MSB, "
889 << "would lead to a negative value so it cannot be recovered!!!!"
890 << std::endl
892 << "TS_MSB: " << fvulCurrentTsMsb[fuCurrDpbIdx] << " Cycle: " << fvuCurrentTsMsbCycle[fuCurrDpbIdx]
893 << " Full TS_MSB: " << fulTsMsbIndexInTs[fuCurrDpbIdx] << " TS Start offset: " << fulTsStartInTsMsb;
894 }
896 }
897 else if (uTsMsbCycleHeader != fvuCurrentTsMsbCycle[fuCurrDpbIdx]) {
900 LOG(debug) << " TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << mstime << " MS Idx "
901 << std::setw(4) << imslice << " Msg Idx " << std::setw(5) << 0 << " DPB " << std::setw(2)
902 << fuCurrDpbIdx << " Old TsMsb " << std::setw(5) << fvulCurrentTsMsb[fuCurrDpbIdx] << " Old MsbCy "
903 << std::setw(5) << fvuCurrentTsMsbCycle[fuCurrDpbIdx] << " New MsbCy " << uTsMsbCycleHeader;
904 }
905 else {
906 LOG(warning) << "TS MSB cycle from MS header does not match current cycle from data "
907 << "for TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << mstime << " MsInTs "
908 << std::setw(3) << imslice << " ====> " << fvuCurrentTsMsbCycle[fuCurrDpbIdx] << " (cnt) VS "
909 << uTsMsbCycleHeader << " (header)";
910 fvuCurrentTsMsbCycle[fuCurrDpbIdx] = uTsMsbCycleHeader;
911 }
912 }
913}
914
915// ---- unpack ----
916bool CbmMuchUnpackAlgo::unpack(const fles::Timeslice* ts, uint16_t icomp, UInt_t imslice)
917{
918 auto msDescriptor = ts->descriptor(icomp, imslice);
919
923 if (fMonitor && 0 == imslice && 0 < fMsStartTime && msDescriptor.idx == ts->start_time()
924 && fMsStartTime < msDescriptor.idx) {
925 fMonitor->FillPerTimesliceCountersHistos(static_cast<double_t>(fMsStartTime) / 1e9);
926 }
927
928 //Current equipment ID, tells from which DPB the current MS is originating
929 const uint32_t uCurrentEquipmentId = msDescriptor.eq_id;
930 const uint8_t* msContent = reinterpret_cast<const uint8_t*>(ts->content(icomp, imslice));
931 const uint32_t uSize = msDescriptor.size;
932
933 fMsStartTime = msDescriptor.idx;
934 LOG(debug) << "Microslice: " << fMsStartTime << " from EqId " << std::hex << uCurrentEquipmentId << std::dec
935 << " has size: " << uSize << " (index " << imslice << ")";
936
937 if (0 == fvbMaskedComponents.size()) fvbMaskedComponents.resize(ts->num_components(), false);
938
939 //Temp holder until current equipment ID is properly filled in MS
940 const uint32_t uCurrDpbId = static_cast<uint32_t>(uCurrentEquipmentId & 0xFFFF);
941
942 if (fMonitor)
943 if (fMonitor->GetDebugMode()) {
944 const double dMsTime = (1e-9) * static_cast<double>(fMsStartTime);
945 if (icomp < fMonitor->GetMaxNbFlibLinks()) {
946 fMonitor->CreateMsComponentSizeHistos(icomp);
947 fMonitor->FillMsSize(icomp, uSize);
948 fMonitor->FillMsSizeTime(icomp, dMsTime, uSize);
949 }
950 }
951
953 auto it = fDpbIdIndexMap.find(uCurrDpbId);
954 if (it == fDpbIdIndexMap.end()) {
955 if (false == fvbMaskedComponents[icomp]) {
956 // LOG(debug) << "---------------------------------------------------------------";
957 // Had to remove this line otherwise we would get circle dependencies in the current stage of cbmroot, since we still have Unpackers in the fles folders, which require the reco folders
958 // LOG(debug) << FormatMsHeaderPrintout(msDescriptor);
959 LOG(warning) << fName << "::unpack(...)::Could not find the sDPB index for AFCK id 0x" << std::hex << uCurrDpbId
960 << std::dec << " in timeslice " << fNrProcessedTs << " in microslice " << imslice << " component "
961 << icomp << "\n"
962 << "If valid this index has to be added in the STS "
963 "parameter file in the DbpIdArray field";
964 fvbMaskedComponents[icomp] = true;
965
968 if (1 == fNrProcessedTs) return true;
969 }
970 else
971 return true;
972
973 // REMARK please check experts, but I think this point can never be reached PR 072021
974 return false;
975 }
976 else
977 fuCurrDpbIdx = fDpbIdIndexMap[uCurrDpbId];
978
979 if (fMonitor) fMonitor->FillMsCntEvo(fMsStartTime);
980
981 if (0 == imslice) {
984 static_cast<uint64_t>(fTsStartTime / (stsxyter::kuHitNbTsBinsBinning * stsxyter::kdClockCycleNs));
985 }
986
987 // Check the current TS_MSb cycle and correct it if wrong
989
990 //Reset internal monitor variables for debugging info
991 if (fMonitor) {
992 if (fMonitor->GetDebugMode()) {
993 fMonitor->ResetDebugInfo();
994 }
995 }
996
997 //Main processing of MS content
998 loopMsMessages(msContent, uSize, imslice);
999
1000 //Output debugging info
1001 if (fMonitor) {
1002 if (fMonitor->GetDebugMode()) {
1003 fMonitor->PrintDebugInfo(fMsStartTime, fNrProcessedTs, msDescriptor.flags, uSize);
1004 }
1005 for (auto itHit = fOutputVec.begin(); itHit != fOutputVec.end(); ++itHit) {
1006 fMonitor->FillDigisTimeInRun(itHit->GetTime());
1007 }
1008 fMonitor->FillVectorSize(ts->index(), fOutputVec.size());
1009 //fMonitor->DrawCanvases();
1010 }
1011
1012 LOG(debug2) << "Total Number of Masked Addresses " << fMaskedNoisyHitsFromCbmMuchAddress;
1013 return true;
1014}
1015
ClassImp(CbmConverterManager)
@ kMuch
Muon detection system.
Definition CbmDefs.h:50
MUCH unpacker algorithms.
bool Bool_t
CbmRoot (+externals) headers.
static uint32_t SetElementId(uint32_t address, int32_t level, int32_t newId)
static uint32_t GetAddress(int32_t station=0, int32_t layer=0, int32_t side=0, int32_t module=0, int32_t sector=0, int32_t channel=0)
uint32_t CreateMuchAddress(uint32_t dpbidx, int32_t febId, uint32_t usChan)
void printAddressMaps(CbmMuchUnpackPar *parset, const std::vector< std::vector< std::vector< int32_t > > > &, const std::vector< std::vector< std::vector< int32_t > > > &)
experts please add description
Bool_t initParSet(FairParGenericSet *parset)
Handles the distribution of the hidden derived classes to their explicit functions.
uint32_t fNrAsicsPerFeb
Number of ASICs per FEB.
bool fbDupliWithoutAdc
If rejecting duplicate digis, enables rejection even if ADC differs.
std::vector< uint64_t > fvulCurrentTsMsb
Current TS MSB for each DPB.
uint64_t fuSkippMessNoValidAddress
For static/inline mapping functions.
virtual std::vector< std::pair< std::string, std::shared_ptr< FairParGenericSet > > > * GetParContainerRequest(std::string geoTag, uint32_t runId)
Get the requested parameter containers. To be defined in the derived classes! Return the required par...
uint32_t fNrElinksPerCrob
Number of eLinks per CROB.
std::vector< std::vector< uint64_t > > fvvulLastTsMsbChan
TS MSB in TS of last hit message for each channel, [ AsicIdx ][ Chan ].
virtual ~CbmMuchUnpackAlgo()
Destroy the Cbm Much Unpack Algo object.
void processErrorInfo(const stsxyter::Message &mess)
experts please add description
uint32_t fNrFebsPerCrob
Number of FEBs per CROB.
std::vector< std::vector< uint16_t > > fvvusLastTsChan
TS of last hit message for each channel, [ AsicIdx ][ Chan ].
std::map< uint32_t, uint32_t > fdAdcCut_perFeb
Minimum adc cut per Feb to store a hit.
CbmMuchUnpackAlgo()
Create the Cbm Much Unpack Algo object.
std::vector< bool > fvbMaskedComponents
Masked components to print out missing component only once.
std::vector< uint32_t > fvuCurrentTsMsbCycle
Current TS MSB cycle for DPB.
bool fbRejectDuplicateDigis
Enables the rejection of duplicate digis.
std::map< uint32_t, uint32_t > fDpbIdIndexMap
Map of DPB Identifier to DPB index.
void initInternalStatus(CbmMuchUnpackPar *parset)
experts please add description here
void processTsMsbInfo(const stsxyter::Message &mess, uint32_t uMessIdx, uint32_t uMsIdx)
experts please add description
void processStatusInfo(const stsxyter::Message &mess, uint32_t uIdx)
experts please add description
bool unpack(const fles::Timeslice *ts, uint16_t icomp, UInt_t imslice)
Unpack a given microslice. To be implemented in the derived unpacker algos.
CbmMuchUnpackPar * fUnpackPar
std::vector< std::vector< bool > > fvvbMaskedChannels
Vector of channel masks, [ NbFeb ][ NbCHanInFeb ], used only if fbUseChannelMask is true.
uint32_t fNrCrobPerDpb
Number of CROBs per DPB.
uint64_t fMaskedNoisyHitsFromCbmMuchAddress
std::vector< std::vector< uint16_t > > fvvusLastAdcChan
ADC of last hit message for each channel, [ AsicIdx ][ Chan ].
std::shared_ptr< CbmMuchUnpackMonitor > fMonitor
Potential (online) monitor for the unpacking process.
void refreshTsMsbFields(const uint32_t imslice, const size_t mstime)
experts please add description here
uint32_t fNrChsPerAsic
Number of Channels per Asic.
Bool_t fbElinkFebMap2022
Backward compatibility with 2022 data.
uint64_t getFullTimeStamp(const uint16_t usRawTs)
Get the Full Time Stamp from raw time stamp.
uint32_t fuNbFebs
Number of FEBs with StsXyter ASICs.
void processEpochInfo(const stsxyter::Message &)
experts please add description marked as not used currently
std::vector< uint64_t > fulTsMsbIndexInTs
Current TS MSB cycle for DPB relative to TS start.
std::vector< int > fElinkIdxToFebIdxVec
Vector used for the translation between eLink index and FEB index.
uint32_t fdAdcCut
Minimum adc cut to store a hit.
Bool_t init()
Intialisation at begin of run. Special inits of the derived algos.
uint32_t fuCurrDpbIdx
Current dpb id.
std::vector< uint32_t > fvbFebAdcCut
ADC cuts for FEBs.
void loopMsMessages(const uint8_t *msContent, const uint32_t uSize, const size_t uMsIdx)
Initialize and transfer the informations to the parameters storage vectors.
void printActiveCrobs(CbmMuchUnpackPar *parset, const std::vector< std::vector< bool > > &vbCrobActiveFlag)
experts please add description
bool fbUseChannelMask
flag if channel mask is to be used or not. Set automatically via MaskNoisyChannels
uint32_t fNrAsicsPerCrob
Number of ASICs per CROB.
uint64_t fuSkippMessNoValidFebPosition
std::vector< double > fvdTimeOffsetNsAsics
Time offsets per Asic???
std::string fParFileName
Settings from parameter file.
void MaskNoisyChannel(const uint32_t uFeb, const uint32_t uChan, const bool bMasked=true)
Mask a Noisy Channel.
void processHitInfo(const stsxyter::Message &mess)
Process the information of the hit message and create a MuchDigi from it.
void initDpbIdIndexMap(CbmMuchUnpackPar *parset)
Initialize the DpbIdIndexMap with the information from the parset.
uint64_t fMsStartTime
Current micro-Slice time.
std::set< uint32_t > fInactiveChannels
uint64_t fulTsStartInTsMsb
Start time of the TS expressed in TS_MSB instead of ns.
uint32_t fNrChsPerFeb
Number of Channels per FEB.
static constexpr UInt_t GetNbAsicsPerCrob()
static constexpr UInt_t GetNbChanPerFeb()
static constexpr UInt_t GetNbFebsPerCrob()
static constexpr UInt_t GetNbCrobsPerDpb()
static constexpr UInt_t GetNbAsicsPerFeb()
static constexpr UInt_t GetNbElinkPerCrob()
Bool_t IsCrobActive(UInt_t uDpbIdx, UInt_t uCrobIdx)
static constexpr UInt_t GetNbChanPerAsic()
UInt_t GetDpbId(UInt_t uDpbIdx)
XPU_D bool IsHitMissedEvts() const
For Hit data: Returns Missed event flag (1 bit field)
XPU_D uint32_t GetTsMsbValBinning() const
For TS MSB data: Returns the TS MSB 29 bit field)
XPU_D uint16_t GetHitAdc() const
For Hit data: Returns ADC value (5 bit field)
XPU_D uint16_t GetHitChannel() const
For Hit data: Returns StsXYTER channel number (7 bit field)
bool PrintMess(std::ostream &os, MessagePrintMask ctrl=MessagePrintMask::msg_print_Human, bool bBinning=true) const
XPU_D uint16_t GetStatusStatus() const
For Status data: Returns the Status field from ACK frame (4 bit field)
XPU_D MessType GetMessType() const
Returns the message type, see enum MessType.
XPU_D uint16_t GetLinkIndexHitBinning() const
XPU_D uint32_t GetData() const
XPU_D uint16_t GetHitTimeBinning() const
XPU_D uint16_t GetStatusLink() const
For Status data: Returns the Link Inedx (9 bit field)
static std::string PrintMessType(MessType type)
XPU_D uint16_t GetMsErrorType() const
For End of MS data: Returns the MS error type field (2 bit field)
XPU_D bool IsMsErrorFlagOn() const
For End of MS data: Returns the MS error flag (1 bit field)
static constexpr uint32_t kuHitNbTsBinsBinning
static constexpr uint64_t kulTsCycleNbBinsBinning
static constexpr double kdClockCycleNs
MessType
Message types.
static constexpr uint16_t kusLenTsMsbValBinning
static constexpr uint16_t kusLenStatStatus
static constexpr uint32_t kuTsMsbNbTsBinsBinning