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*/, std::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 LOG(debug) << fName << "::initParSetAsic - ";
106
107 //Type of each module: 0 for connectors on the right, 1 for connectors on the left
108 // std::vector<int32_t> viModuleType;
109
110 // STS address for the first strip of each module
111 // std::vector<int32_t> viModAddress;
112
113 // Idx of the STS module for each FEB, [ NbDpb ][ NbCrobPerDpb ][ NbFebsPerCrob ], -1 if inactive
114 //std::vector<std::vector<std::vector<int32_t>>> viFebModuleIdx;
115
116 // Array to hold the active flag for all CROBs, [ NbDpb ][ NbCrobPerDpb ]
117 std::vector<std::vector<bool>> vbCrobActiveFlag;
118
119 //STS module side for each FEB, [ NbDpb ][ NbCrobPerDpb ][ NbFebsPerCrob ], 0 = P, 1 = N, -1 if inactive
120 //std::vector<std::vector<std::vector<int32_t>>> viFebModuleSide;
121
122 // Total number of STS modules in the setup
123 //const uint32_t uNbModules = parset->GetNbOfModules();
124 //LOG(debug) << "Nr. of STS Modules: " << uNbModules;
125
126 // Total number of MuCH DPBs in system
127 const uint32_t uNbOfDpbs = parset->GetNrOfDpbs();
128 LOG(debug) << "Nr. of MuCH DPBs: " << uNbOfDpbs;
129
130 // Get Nr of Febs
131 fuNbFebs = parset->GetNrOfFebs();
132 LOG(debug) << "Nr. of FEBs: " << fuNbFebs;
133
134 // Get Nr of eLinks per CROB
136
137 // Get Nr of ASICs per CROB
139
140 // Get Nr of CROBs per DPB
142
143 // Get Number of ASICs per FEB
145
146 // Get Number of Channels per Asic
148
149 // Get Number of Channels per FEB
150 fNrChsPerFeb = parset->GetNbChanPerFeb();
151
152 // Get Number of FEBs per CROB
154
155 /*
156 for (size_t ielink = 0; ielink < fNrElinksPerCrob; ++ielink) {
157 fElinkIdxToFebIdxVec.emplace_back(parset->ElinkIdxToFebIdx(ielink));
158 fElinkIdxToAsicIdxVec.emplace_back(
159 std::make_pair(parset->ElinkIdxToAsicIdxFebA(ielink), parset->ElinkIdxToAsicIdxFebB(ielink)));
160 }*/
161
162 // Get Nr of Asics
163 const uint32_t uNbStsXyters = parset->GetNrOfFebs();
164 LOG(debug) << "Nr. of StsXyter ASICs: " << uNbStsXyters;
165
166 //Initialize temporary "per Feb" fields
167 //initTempVectors(parset, &viModuleType, &viModAddress, &viFebModuleIdx, &vbCrobActiveFlag, &viFebModuleSide);
168 //initTempVectors(parset, &vbCrobActiveFlag);
169
170 // Initialize ADC cuts for FEBs
172 for (auto cut : fdAdcCut_perFeb) {
173 fvbFebAdcCut[cut.first] = cut.second;
174 }
175 // Read dpb index map from parameter container
176 initDpbIdIndexMap(parset);
177
178 if (fvdTimeOffsetNsAsics.size() < uNbStsXyters) {
179 fvdTimeOffsetNsAsics.resize(uNbStsXyters, 0.0);
180 }
181
182 /*
183 //Initialize class-wide "per Feb" fields
184 fviFebType.resize(uNbOfDpbs);
185
186 for (uint32_t uDpb = 0; uDpb < uNbOfDpbs; ++uDpb) {
187 fviFebType[uDpb].resize(fNrCrobPerDpb);
188 for (uint32_t uCrobIdx = 0; uCrobIdx < fNrCrobPerDpb; ++uCrobIdx) {
189 fviFebType[uDpb][uCrobIdx].resize(parset->GetNbFebsPerCrob(), -1);
190 for (uint32_t uFebIdx = 0; uFebIdx < parset->GetNbFebsPerCrob(); ++uFebIdx) {
191 //fvbFebPulser.push_back(parset->IsFebPulser(uDpb, uCrobIdx, uFebIdx));
192 //fvdFebAdcGain.push_back(parset->GetFebAdcGain(uDpb, uCrobIdx, uFebIdx));
193 //fvdFebAdcOffs.push_back(parset->GetFebAdcOffset(uDpb, uCrobIdx, uFebIdx));
194
195 if (0 <= viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]
196 && static_cast<uint32_t>(viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]) < uNbModules
197 && 0 <= viFebModuleSide[uDpb][uCrobIdx][uFebIdx] && viFebModuleSide[uDpb][uCrobIdx][uFebIdx] < 2) {
198 switch (viModuleType[viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]]) {
199 case 0: // FEB-8-1 with ZIF connector on the right
200 {
201 // P side (0) has type A (0)
202 // N side (1) has type B (1)
203 fviFebType[uDpb][uCrobIdx][uFebIdx] = viFebModuleSide[uDpb][uCrobIdx][uFebIdx];
204
211 fviFebAddress.push_back(viModAddress[viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]]);
212 // + (viFebModuleSide[uDpb][uCrobIdx][uFebIdx] << 25));
213 fviFebSide.push_back(viFebModuleSide[uDpb][uCrobIdx][uFebIdx]);
214 break;
215 } // case 0: // FEB-8-1 with ZIF connector on the right
216 case 1: // FEB-8-1 with ZIF connector on the left
217 {
218 // P side (0) has type B (1)
219 // N side (1) has type A (0)
220 fviFebType[uDpb][uCrobIdx][uFebIdx] = !(viFebModuleSide[uDpb][uCrobIdx][uFebIdx]);
221
228 fviFebAddress.push_back(viModAddress[viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]]);
229 // + ((!viFebModuleSide[uDpb][uCrobIdx][uFebIdx]) << 25));
230 fviFebSide.push_back(viFebModuleSide[uDpb][uCrobIdx][uFebIdx]);
231 break;
232 } // case 1: // FEB-8-1 with ZIF connector on the left
233 default:
234 LOG(fatal) << Form("Bad module type for DPB #%02u CROB #%u FEB %02u: %d", uDpb, uCrobIdx, uFebIdx,
235 viModuleType[viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]]);
236 break;
237 }
238 } // FEB active and module index OK
239 else if (-1 == viFebModuleIdx[uDpb][uCrobIdx][uFebIdx] || -1 == viFebModuleSide[uDpb][uCrobIdx][uFebIdx]) {
240 fviFebAddress.push_back(0);
241 fviFebSide.push_back(-1);
242 } // Module index or type is set to inactive
243 else {
244 LOG(fatal) << Form("Bad module Index and/or Side for DPB #%02u CROB "
245 "#%u FEB %02u: %d %d",
246 uDpb, uCrobIdx, uFebIdx, viFebModuleIdx[uDpb][uCrobIdx][uFebIdx],
247 viFebModuleSide[uDpb][uCrobIdx][uFebIdx]);
248 } // Bad module index or type for this FEB
249 }
250 }
251 }
252*/
253
254 vbCrobActiveFlag.resize(uNbOfDpbs);
255 for (uint32_t uDpb = 0; uDpb < uNbOfDpbs; ++uDpb) {
256 vbCrobActiveFlag[uDpb].resize(fNrCrobPerDpb);
257 for (uint32_t uCrobIdx = 0; uCrobIdx < fNrCrobPerDpb; ++uCrobIdx) {
258 vbCrobActiveFlag[uDpb][uCrobIdx] = parset->IsCrobActive(uDpb, uCrobIdx);
259 }
260 }
261
262 printActiveCrobs(parset, vbCrobActiveFlag);
263 //printAddressMaps(parset, viFebModuleIdx, viFebModuleSide);
264
265 LOG(debug) << "Unpacking data in bin sorter FW mode";
266 initInternalStatus(parset);
267
268 if (fMonitor) {
269 fMonitor->Init(parset);
270 LOG(info) << fName << "::initParSet - Successfully initialized MUCH monitor";
271 }
272
273 return kTRUE;
274}
275
276// ---- initTempVectors ----
277
278//ToDo: Temporary vectors to be initialized
279
280// ---- initInternalStatus ----
282{
283
284 const uint32_t uNbOfDpbs = parset->GetNrOfDpbs();
285 const uint32_t uNbStsXyters = parset->GetNrOfAsics();
286
287 fvulCurrentTsMsb.resize(uNbOfDpbs);
288 fvuCurrentTsMsbCycle.resize(uNbOfDpbs);
289 fulTsMsbIndexInTs.resize(uNbOfDpbs);
290 for (uint32_t uDpb = 0; uDpb < uNbOfDpbs; ++uDpb) {
291 fvulCurrentTsMsb[uDpb] = 0;
292 fvuCurrentTsMsbCycle[uDpb] = 0;
293 fulTsMsbIndexInTs[uDpb] = 0;
294 }
295
296 fvvusLastTsChan.resize(uNbStsXyters);
297 fvvusLastAdcChan.resize(uNbStsXyters);
298 fvvulLastTsMsbChan.resize(uNbStsXyters);
299 for (uint32_t uAsicIdx = 0; uAsicIdx < uNbStsXyters; ++uAsicIdx) {
300 fvvusLastTsChan[uAsicIdx].resize(fNrChsPerAsic, 0);
301 fvvusLastAdcChan[uAsicIdx].resize(fNrChsPerAsic, 0);
302 fvvulLastTsMsbChan[uAsicIdx].resize(fNrChsPerAsic, 0);
303 }
304}
305
306// ---- loopMsMessages ----
307void CbmMuchUnpackAlgo::loopMsMessages(const uint8_t* msContent, const uint32_t uSize, const size_t uMsIdx)
308{
309 // If not integer number of message in input buffer, print warning/error
310 if (0 != (uSize % sizeof(stsxyter::Message))) {
311 LOG(error) << "The input microslice buffer does NOT "
312 << "contain only complete sDPB messages!";
313 }
314 // Compute the number of complete messages in the input microslice buffer
315 const uint32_t uNbMessages = (uSize - (uSize % sizeof(stsxyter::Message))) / sizeof(stsxyter::Message);
316
317 // Prepare variables for the loop on contents
318 const stsxyter::Message* pMess = reinterpret_cast<const stsxyter::Message*>(msContent);
319
320 for (uint32_t uIdx = 0; uIdx < uNbMessages; uIdx++) {
322 const stsxyter::MessType typeMess = pMess[uIdx].GetMessType();
323
324 LOG(debug2) << " Msg Idx " << std::setw(6) << uIdx << " Type " << stsxyter::Message::PrintMessType(typeMess);
325
326 if (fMonitor)
327 if (fMonitor->GetDebugMode()) {
328 fMonitor->ProcessDebugInfo(pMess[uIdx], fuCurrDpbIdx);
329 }
330
331 switch (typeMess) {
333 processHitInfo(pMess[uIdx]);
334 break;
335 }
337 processTsMsbInfo(pMess[uIdx], uIdx, uMsIdx);
338 break;
339 }
341 processEpochInfo(pMess[uIdx]);
342 if (0 < uIdx) {
343 LOG(warning) << "CbmMuchUnpackAlgo::loopMsMessages => "
344 << "EPOCH message at unexpected position in MS: message " << uIdx << " VS message 0 expected!";
345 }
346 break;
347 }
349 processStatusInfo(pMess[uIdx], uIdx);
350 break;
351 }
353 break;
354 }
356 processErrorInfo(pMess[uIdx]);
357 break;
358 }
360 break;
361 }
362 default: {
363 LOG(fatal) << "CbmMuchUnpackAlgo::loopMsMessages => "
364 << "Unknown message type, should never happen, stopping "
365 "here! Type found was: "
366 << static_cast<int>(typeMess);
367 }
368 }
369 }
370}
371
372// ---- MaskNoisyChannel ----
373void CbmMuchUnpackAlgo::MaskNoisyChannel(const uint32_t uFeb, const uint32_t uChan, const bool bMasked)
374{
375 if (false == fbUseChannelMask) {
376 fbUseChannelMask = true;
378 for (uint32_t uFebIdx = 0; uFebIdx < fuNbFebs; ++uFebIdx) {
379 fvvbMaskedChannels[uFebIdx].resize(fNrChsPerFeb, false);
380 }
381 }
382 if (uFeb < fuNbFebs && uChan < fNrChsPerFeb)
383 fvvbMaskedChannels[uFeb][uChan] = bMasked;
384 else
385 LOG(fatal) << "CbmMuchUnpackAlgo::MaskNoisyChannel => Invalid FEB "
386 "and/or CHAN index:"
387 << Form(" %u vs %u and %u vs %u", uFeb, fuNbFebs, uChan, fNrChsPerFeb);
388}
389
390
391// ---- printActiveCrobs ----
393 const std::vector<std::vector<bool>>& vbCrobActiveFlag)
394{
395 for (uint32_t uDpb = 0; uDpb < parset->GetNrOfDpbs(); ++uDpb) {
396 TString sPrintoutLine = Form("DPB #%02u CROB Active ?: ", uDpb);
397 for (uint32_t uCrobIdx = 0; uCrobIdx < fNrCrobPerDpb; ++uCrobIdx) {
398 sPrintoutLine += Form("%1u", (vbCrobActiveFlag[uDpb][uCrobIdx] == true));
399 LOG(debug) << "at function printActiveCrobs";
400 }
401 LOG(debug) << sPrintoutLine;
402 }
403}
404
405// ---- printAddressMaps ----
406//To Do: fill the body accordingly
408 const std::vector<std::vector<std::vector<int32_t>>>& /*viFebModuleIdx*/,
409 const std::vector<std::vector<std::vector<int32_t>>>& /*viFebModuleSide*/)
410{
411
412 LOG(info) << "Currently this function not printing any info for MuCh.";
413 /*
414 uint32_t uGlobalFebIdx = 0;
415 for (uint32_t uDpb = 0; uDpb < parset->GetNrOfDpbs(); ++uDpb) {
416 for (uint32_t uCrobIdx = 0; uCrobIdx < fNrCrobPerDpb; ++uCrobIdx) {
417 LOG(debug) << Form("DPB #%02u CROB #%u: ", uDpb, uCrobIdx);
418 for (uint32_t uFebIdx = 0; uFebIdx < parset->GetNbFebsPerCrob(); ++uFebIdx) {
419 if (0 <= viFebModuleIdx[uDpb][uCrobIdx][uFebIdx])
420 LOG(debug) << Form(" FEB #%02u (%02u): Mod. Idx = %03d Side %c (%2d) Type %c "
421 "(%2d) (Addr. 0x%08x) ADC gain %4.0f e- ADC Offs %5.0f e-",
422 uFebIdx, uGlobalFebIdx, viFebModuleIdx[uDpb][uCrobIdx][uFebIdx],
423 1 == viFebModuleSide[uDpb][uCrobIdx][uFebIdx] ? 'N' : 'P',
424 viFebModuleSide[uDpb][uCrobIdx][uFebIdx],
425 1 == fviFebType[uDpb][uCrobIdx][uFebIdx] ? 'B' : 'A', fviFebType[uDpb][uCrobIdx][uFebIdx],
426 fviFebAddress[uGlobalFebIdx], fvdFebAdcGain[uGlobalFebIdx], fvdFebAdcOffs[uGlobalFebIdx]);
427 else
428 LOG(debug) << Form("Disabled FEB #%02u (%02u): Mod. Idx = %03d Side %c (%2d) Type %c "
429 "(%2d) (Addr. 0x%08x) ADC gain %4.0f e- ADC Offs %5.0f e-",
430 uFebIdx, uGlobalFebIdx, viFebModuleIdx[uDpb][uCrobIdx][uFebIdx],
431 1 == viFebModuleSide[uDpb][uCrobIdx][uFebIdx] ? 'N' : 'P',
432 viFebModuleSide[uDpb][uCrobIdx][uFebIdx],
433 1 == fviFebType[uDpb][uCrobIdx][uFebIdx] ? 'B' : 'A', fviFebType[uDpb][uCrobIdx][uFebIdx],
434 fviFebAddress[uGlobalFebIdx], fvdFebAdcGain[uGlobalFebIdx], fvdFebAdcOffs[uGlobalFebIdx]);
435 uGlobalFebIdx++;
436 }
437 }
438 }
439*/
440}
441
442// -------------------------------------------------------------------------
444{
445 if (mess.IsMsErrorFlagOn()) {
446 // 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
447 if (fMonitor) {
448 fMonitor->FillMsErrorsEvo(fMsStartTime, mess.GetMsErrorType());
449 }
450 if (fOptOutBVec)
451 fOptOutBVec->emplace_back(
453 }
454}
455
456// ---- processHitInfo ----
458{
459 const uint16_t usElinkIdx = mess.GetLinkIndexHitBinning();
460 // const uint32_t uCrobIdx = usElinkIdx / fNrElinksPerCrob;
461 // Get the asic index
462 //uint32_t uAsicIdx = getFebIndex(fuCurrDpbIdx, uCrobIdx, usElinkIdx);
463 //Below will generate asicidx from 0 to 8. According to Elink Number.
464 uint32_t asicidx = fUnpackPar->ElinkIdxToFebIdx(usElinkIdx);
465 //Below will generate uAsicIdx from 0 to maximum number of FEBs.
466 uint32_t uAsicIdx = fuCurrDpbIdx * fUnpackPar->GetNbFebsPerDpb() + asicidx;
467 //Below will generate FEB Position Number according to GEM and RPC.
468 int32_t uFebIdx = fUnpackPar->GetFebId(uAsicIdx);
469 if (-1 == uFebIdx) {
470 LOG(warning) << "CbmMuchUnpackAlgo::processHitInfo => "
471 << "Particular FEB is not connected. Digi is not created for this hit. Check FEB number " << uAsicIdx
472 << " generate FEB Position " << uFebIdx;
474 return;
475 }
476 if (-2 == uFebIdx) {
477 LOG(error) << "CbmMuchUnpackAlgo::processHitInfo => "
478 << "Wrong Elink Idx! "
479 << " Feb " << uFebIdx << " Elink " << usElinkIdx;
481 return;
482 }
483 const uint16_t usChan = mess.GetHitChannel();
484 const uint16_t usRawAdc = mess.GetHitAdc();
485 const uint16_t usRawTs = mess.GetHitTimeBinning();
486 const uint32_t uChanInFeb = usChan + fNrChsPerAsic * (uAsicIdx % fNrAsicsPerFeb);
487
488 // Compute the Full time stamp
489 const uint64_t ulHitTime = getFullTimeStamp(usRawTs);
490
491 //uFebIdx += ( fuCurrDpbIdx * fNrCrobPerDpb + ____CrobIndexCalculationIfNeeded___() ) * fuNbFebsPerCrob;
492 //uncomment below line if kuNbCrobsPerDpb > 1
493 //uFebIdx += (fuCurrDpbIdx * fNrCrobPerDpb) * fNrFebsPerCrob; //no Crob index calculation for now
494
495
496 if (fMonitor) fMonitor->CountRawHit(uFebIdx, uChanInFeb);
497
499 if (fvbFebAdcCut[uFebIdx] < usRawAdc) {
502 if (false == fbUseChannelMask || false == fvvbMaskedChannels[uFebIdx][uChanInFeb]) {
503
506 if (usRawTs == fvvusLastTsChan[uAsicIdx][usChan]
507 && (fbDupliWithoutAdc || usRawAdc == fvvusLastAdcChan[uAsicIdx][usChan])
508 && fulTsMsbIndexInTs[fuCurrDpbIdx] == fvvulLastTsMsbChan[uAsicIdx][usChan]) {
510 LOG(debug1) << "CbmMuchUnpackAlgo::processHitInfo => "
511 << Form("Rejecting duplicate on Asic %3u channel %3u, TS %3u, ADC %2u", uAsicIdx, usChan, usRawTs,
512 usRawAdc);
513
514 if (fMonitor) fMonitor->FillDuplicateHitsAdc(uAsicIdx, uChanInFeb, usRawAdc);
515 return;
516 } // if same TS, (ADC,) TS MSB, TS MSB cycle, reject
517 fvvusLastTsChan[uAsicIdx][usChan] = usRawTs;
518 fvvusLastAdcChan[uAsicIdx][usChan] = usRawAdc;
520 } // if (fbRejectDuplicateDigis)
521
522 //uint32_t uChanInMod = usChan + fNrChsPerAsic * (uAsicIdx % fNrAsicsPerFeb);
523
527
528 //if (0 == fviFebSide[uFebIdx])
529 // uChanInMod = fNrChsPerFeb - uChanInMod - 1 // Invert channel order
530 // + fNrChsPerFeb; // Offset for P (back) side
531
532 const double_t tsreltime = static_cast<double_t>(ulHitTime) * stsxyter::kdClockCycleNs;
533 double dTimeInNs = tsreltime - fSystemTimeOffset;
534 if (uAsicIdx < fvdTimeOffsetNsAsics.size()) dTimeInNs -= fvdTimeOffsetNsAsics[uAsicIdx];
535
536 const uint64_t ulTimeInNs = static_cast<uint64_t>(dTimeInNs);
537 //const double dCalAdc = fvdFebAdcOffs[uFebIdx] + (usRawAdc - 1) * fvdFebAdcGain[uFebIdx];
538
539 //if (0 == fviFebAddress[uFebIdx] || -1 == fviFebSide[uFebIdx]) {
540 // LOG(error) << Form("Digi on disabled FEB %02u has address 0x%08x and side %d", uFebIdx, fviFebAddress[uFebIdx],
541 // fviFebSide[uFebIdx]);
542 //}
543
544 if (fMonitor) fMonitor->CountDigi(uAsicIdx, uChanInFeb);
545 //Checking for Raw channel value
546 if (usChan > 127) LOG(debug) << "ERROR !!! Channel in hit message is out of range " << usChan;
547 // uFebIdx is FEB position in the GEM and RPC
548 const uint32_t address = CreateMuchAddress(fuCurrDpbIdx, uFebIdx, usChan);
549
550 // Masking Noisy Channel. If Address is part of Inactive Channel List
551 if (fInactiveChannels.count(address)) {
552 //Counting number of hits fall on noisy channel
554 return;
555 }
556
557
558 //const uint32_t address = CreateMuchAddress(fuCurrDpbIdx, uFebIdx, uChanInFeb);
559 LOG(debug) << "Created Much Address = " << address << " from fuCurrDpbIdx " << fuCurrDpbIdx << " Feb Id "
560 << uFebIdx << " Channnel Id " << uChanInFeb;
561 if (address) {
563 // Storing Pulser FEB Data in another output stream (pulser feb gives -7 )
564 if (-7 == uFebIdx) {
565 //presently for Pulser Output CbmMuchDigi address is 0
566 fOptOutAVec->emplace_back(CbmMuchDigi(address, usRawAdc, ulTimeInNs));
567 return;
568 } // if (-7 == uFebIdx)
569 fOutputVec.emplace_back(CbmMuchDigi(address, usRawAdc, ulTimeInNs));
570 }
571 else {
572 if (-7 != uFebIdx) { //
573 LOG(warning) << "Digi not created due to generated address is " << address;
574 }
576 }
578 //Commented below 6 lines as we do not use FebPulser Vector
579 //if (fvbFebPulser[uFebIdx]) {
580 // if (fOptOutAVec) {
581 // fOptOutAVec->emplace_back(CbmMuchDigi(address, usRawAdc, ulTimeInNs));
582 // } // if (fOptOutAVec)
583 // } // if (fvbFebPulser[uFebIdx])
584 //else {
585 // fOutputVec.emplace_back(CbmMuchDigi(address, usRawAdc, ulTimeInNs));
586 //} // else of if (fvbFebPulser[uFebIdx])
587
589 if (mess.IsHitMissedEvts())
590 if (fOptOutBVec)
591 fOptOutBVec->emplace_back(
592 CbmErrorMessage(ECbmModuleId::kMuch, dTimeInNs, uAsicIdx, 1 << stsxyter::kusLenStatStatus, usChan));
593 }
594 }
595
596 if (fMonitor) {
597 // Convert the Hit time in bins within the TS to Hit time in secondes within Unix frame (UTC or TAI)
598 const double dHitTimeAbsSec =
599 (static_cast<double_t>(ulHitTime) * stsxyter::kdClockCycleNs - fSystemTimeOffset + fTsStartTime) * 1e-9;
600
601 // Prepare monitoring values
602 const uint32_t uAsicInFeb = uAsicIdx % fNrAsicsPerFeb;
603 const double dCalAdc = usRawAdc;
604 // const double dCalAdc = fvdFebAdcOffs[uFebIdx] + (usRawAdc - 1) * fvdFebAdcGain[uFebIdx];
605
606 fMonitor->FillHitMonitoringHistos(uFebIdx, usChan, uChanInFeb, usRawAdc, dCalAdc, usRawTs, mess.IsHitMissedEvts());
607 fMonitor->FillHitEvoMonitoringHistos(uFebIdx, uAsicIdx, uAsicInFeb, uChanInFeb, dHitTimeAbsSec,
608 mess.IsHitMissedEvts());
609
610 if (fMonitor->GetDebugMode()) {
611 fMonitor->FillHitDebugMonitoringHistos(uAsicIdx, usChan, usRawAdc, usRawTs, mess.IsHitMissedEvts());
612 }
613 }
614}
615
616//---------------CreateMuchDigi -------
617//To do address need to be checked carefully
618uint32_t CbmMuchUnpackAlgo::CreateMuchAddress(uint32_t dpbidx, int32_t iFebId, uint32_t usChan)
619{
620 // For generating Station number (GEM1 station = 0, GEM2 station = 1 and RPC station = 2)
622 int32_t station = -1;
623 int32_t layer = -1;
624 if (iFebId == -7) //Pulser FEB
625 {
626 station = 6; // for Pulser
627 layer = 0; //
628 }
629 else if (dpbidx == 0 || dpbidx == 1 || dpbidx == 2) //First 3 DPBs are for GEM-1
630 {
631 station = 0; // for mCBM setup
632 layer = 0; // Station 0 for GEM-A and station 1 for Module GEM-B
633 }
634 else if (dpbidx == 4 || dpbidx == 5 || dpbidx == 6) //Last 3 DPBs are for GEM-2 after 10/04/2022
635 {
636 station = 1; // for mCBM setup station
637 layer = 0; // 0 for Module GEM-A and 1 for Module GEM-B
638 }
639 else if (dpbidx == 3) {
640 station = 2; // for mCBM setup only one station
641 layer = 0; //
642 }
643 else {
644 LOG(warning) << "Wrong DPB Id x " << dpbidx;
645 return 0;
646 } //No address generated.
647 //Common layer side module will be 0 only for mCBM 2022
648 int32_t layerside = 0; // 0 in mCBM
649 int32_t sModule = 0; // 0 in mCBM
650
651 int32_t sSector = -9; //channel values are from 0-96 therefore as per CbmMuchAddress it is sector
652 int32_t sChannel = -9; //sector values are from 0-22 therefore as per CbmMuchAddress it is channel
653
654 //Int_t usChan = itHitIn->GetChan();
655
656 // ----------------------------- //
657 // Channel flip in stsXYTER v2.1 : 0<->1, 2<->3, 3<->4 and so on...
658 auto fiFlag = 1;
659 if (fiFlag == 1) {
660 if (usChan % 2 == 0)
661 usChan = usChan + 1;
662 else
663 usChan = usChan - 1;
664 }
665 // ---------------------------- //
666 // auto iFebId = >GetFebId(febId);
667 // ---------------------------- //
668 // PadX means CHANNEL for CbmMuchAddress
669 // PadY means SECTOR for CbmMuchAddress
670 //Due to two FLEX cable connected to single FEB; First Flex Connector number 1 - 63 and second flex connector number 64 - 127
671 //in few FEB positioned these flex connectors are flipped so below correction applied.
672 if (station == 0 && fiFlag == 1 && layer == 0) { // First layer (GEM1) has old readout PCB
673 if (iFebId == 0 || iFebId == 1 || iFebId == 2 || iFebId == 3 || iFebId == 4 || iFebId == 8 || iFebId == 9
674 || iFebId == 10 || iFebId == 11 || iFebId == 17) {
675 sChannel = fUnpackPar->GetPadXA(iFebId, 127 - usChan);
676 sSector = fUnpackPar->GetPadYA(iFebId, 127 - usChan);
677 }
678 else {
679 sChannel = fUnpackPar->GetPadXA(iFebId, usChan);
680 sSector = fUnpackPar->GetPadYA(iFebId, usChan);
681 }
682 } // if( fiFlag == 1 && layer == 0 )
683 else if (station == 1 && fiFlag == 1 && layer == 0) { // second layer (GEM2) has new readout PCB
684 if (iFebId == 0 || iFebId == 1 || iFebId == 2 || iFebId == 3 || iFebId == 4 || iFebId == 8 || iFebId == 9
685 || iFebId == 10 || iFebId == 11 || iFebId == 17) {
686 sChannel = fUnpackPar->GetPadXB(iFebId, 127 - usChan);
687 sSector = fUnpackPar->GetPadYB(iFebId, 127 - usChan);
688 }
689 else {
690 sChannel = fUnpackPar->GetPadXB(iFebId, usChan);
691 sSector = fUnpackPar->GetPadYB(iFebId, usChan);
692 }
693 } // else if( fiFlag == 1 && layer == 1 )
694 else if (station == 0 || station == 1) { // Both layer with same type of PCB (Probably below is not necessary)
695 if (iFebId == 0 || iFebId == 1 || iFebId == 2 || iFebId == 3 || iFebId == 4 || iFebId == 8 || iFebId == 9
696 || iFebId == 10 || iFebId == 11 || iFebId == 17) {
697 sChannel = fUnpackPar->GetPadXA(iFebId, 127 - usChan);
698 sSector = fUnpackPar->GetPadYA(iFebId, 127 - usChan);
699 }
700 else {
701 sChannel = fUnpackPar->GetPadXA(iFebId, usChan);
702 sSector = fUnpackPar->GetPadYA(iFebId, usChan);
703 }
704 } // else{
705 else if (station == 2) { //For RPC
706 sChannel = fUnpackPar->GetPadXRpc(iFebId, usChan);
707 sSector = fUnpackPar->GetPadYRpc(iFebId, usChan);
708 }
709 else // Checking for the not connected or misconnected pads
710 {
711 LOG(debug) << "Sector " << sSector << " channel " << sChannel << " is not connected or misconnected to pad. "
712 << " corresponding Feb is " << iFebId << " and uschan " << usChan << " DPB id " << dpbidx
713 << " Skipping this hit message.";
714 return 0;
715 }
716 //Creating Unique address of the particular channel of GEM
717 //UInt_t address = CbmMuchAddress::GetAddress(station, layer, layerside, sModule, sChannel, sSector);
718 uint32_t address = CbmMuchAddress::GetAddress(station, layer, layerside, sModule, sSector, sChannel);
719 LOG(debug) << "Raw address " << address;
720 address = CbmMuchAddress::SetElementId(address, 1, station);
721 LOG(debug) << "After adding station " << address << " binary " << std::bitset<32>(address);
722 address = CbmMuchAddress::SetElementId(address, 2, layer);
723 LOG(debug) << "After adding Layer " << address << " binary " << std::bitset<32>(address);
724 address = CbmMuchAddress::SetElementId(address, 3, layerside);
725 LOG(debug) << "After adding Layer Side " << address << " binary " << std::bitset<32>(address);
726 address = CbmMuchAddress::SetElementId(address, 4, sModule);
727 LOG(debug) << "After adding module " << address << " binary " << std::bitset<32>(address);
728 address = CbmMuchAddress::SetElementId(address, 5, sSector);
729 LOG(debug) << "After adding sector " << address << " binary " << std::bitset<32>(address);
730 address = CbmMuchAddress::SetElementId(address, 6, sChannel);
731 LOG(debug) << "After adding channel " << address << " binary " << std::bitset<32>(address);
732 /*
733 Double_t dTimeInNs = itHitIn->GetTs() * stsxyter::kdClockCycleNs - fdTimeOffsetNs;
734 if (uAsicIdx < fvdTimeOffsetNsAsics.size()) dTimeInNs -= fvdTimeOffsetNsAsics[uAsicIdx];
735 ULong64_t ulTimeInNs = static_cast<ULong64_t>(dTimeInNs);
736
738 // fDigiVect.push_back( CbmMuchDigi( address, itHitIn->GetAdc(), ulTimeInNs ) );
739
741
742 CbmMuchBeamTimeDigi* digi = new CbmMuchBeamTimeDigi(address, itHitIn->GetAdc(), ulTimeInNs);
743 LOG(debug) << "Sector " << sSector << " channel " << sChannel << " layer " << layer << " Address " << address
744 << " Time " << ulTimeInNs;
745
746 digi->SetPadX(sSector);
747 digi->SetPadY(sChannel);
748 digi->SetRocId(itHitIn->GetDpb());
749 digi->SetNxId(itHitIn->GetAsic());
750 digi->SetNxCh(itHitIn->GetChan()); */
751 // Add Elink also in the stsxyter::FinalHit as one more variable such that may be used.
752 //digi.SetElink(itHitIn->GetElink());
753
754 return address;
755}
756
757//----------------------------------
758
759// ---- processStatusInfo ----
761{
762 // again fMonitor settings used for debugging printouts, I would propose to separate this
763 if (fMonitor)
764 if (fMonitor->GetDebugMode()) {
765 std::cout << Form("DPB %2u TS %12lu mess %5u ", fuCurrDpbIdx, fTsIndex, uIdx);
767 }
768
769 const uint16_t usElinkIdx = mess.GetStatusLink();
770 // const uint32_t uCrobIdx = usElinkIdx / fNrElinksPerCrob;
771 const int32_t uFebIdx = fElinkIdxToFebIdxVec.at(usElinkIdx);
772 if (-1 == uFebIdx) {
773 LOG(warning) << "CbmMuchUnpackAlgo::processStatusInfo => "
774 << "Wrong elink Idx! Elink raw " << Form("%d remap %d", usElinkIdx, uFebIdx);
775 return;
776 }
777 //const uint32_t uAsicIdx = getFebIndex(fuCurrDpbIdx, uCrobIdx, usElinkIdx);
778 //Below will generate asicidx from 0 to 8. According to Elink Number.
779 uint32_t asicidx = fUnpackPar->ElinkIdxToFebIdx(usElinkIdx);
780 //Below will generate uAsicIdx from 0 to maximum number of FEBs.
781 uint32_t uAsicIdx = fuCurrDpbIdx * fUnpackPar->GetNbFebsPerDpb() + asicidx;
782 //Below will generate FEB Position Number according to GEM and RPC.
783 //int32_t uFebIdx = fUnpackPar->GetFebId(uAsicIdx);
784 if (fMonitor) {
785 const uint16_t usStatusField = mess.GetStatusStatus();
786 fMonitor->FillMuchStatusMessType(uAsicIdx, usStatusField);
787 }
789 const int64_t ulTime = getFullTimeStamp(0);
790
792 const double dTimeNs = ulTime * stsxyter::kdClockCycleNs;
793 if (fOptOutBVec)
794 fOptOutBVec->emplace_back(
795 CbmErrorMessage(ECbmModuleId::kMuch, dTimeNs, uAsicIdx, mess.GetStatusStatus(), mess.GetData()));
796}
797
798
799// ---- processTsMsbInfo ----
800void CbmMuchUnpackAlgo::processTsMsbInfo(const stsxyter::Message& mess, uint32_t uMessIdx, uint32_t uMsIdx)
801{
802 const uint32_t uVal = mess.GetTsMsbValBinning();
803
804 // Update Status counters
805 if (uVal < fvulCurrentTsMsb[fuCurrDpbIdx]) {
806
807 LOG(debug) << " TS " << std::setw(12) << fTsIndex << " MS Idx " << std::setw(4) << uMsIdx << " Msg Idx "
808 << std::setw(5) << uMessIdx << " DPB " << std::setw(2) << fuCurrDpbIdx << " Old TsMsb " << std::setw(5)
809 << fvulCurrentTsMsb[fuCurrDpbIdx] << " Old MsbCy " << std::setw(5) << fvuCurrentTsMsbCycle[fuCurrDpbIdx]
810 << " new TsMsb " << std::setw(5) << uVal;
811
813 }
814 if (uVal != fvulCurrentTsMsb[fuCurrDpbIdx] + 1
818 && !(1 == uMessIdx && 0 == uMsIdx)
820 && !(uVal == fvulCurrentTsMsb[fuCurrDpbIdx] && 2 == uMessIdx)
822 && uVal < fvulCurrentTsMsb[fuCurrDpbIdx]) {
823 LOG(debug) << "TS MSB Jump in "
824 << " TS " << std::setw(12) << fTsIndex << " MS Idx " << std::setw(4) << uMsIdx << " Msg Idx "
825 << std::setw(5) << uMessIdx << " DPB " << std::setw(2) << fuCurrDpbIdx << " => Old TsMsb "
826 << std::setw(5) << fvulCurrentTsMsb[fuCurrDpbIdx] << " new TsMsb " << std::setw(5) << uVal;
827 }
828
830
831 LOG(debug1) << " TS " << std::setw(12) << fTsIndex << " MS Idx " << std::setw(4) << uMsIdx << " Msg Idx "
832 << std::setw(5) << uMessIdx << " DPB " << std::setw(2) << fuCurrDpbIdx << " TsMsb " << std::setw(5)
833 << fvulCurrentTsMsb[fuCurrDpbIdx] << " MsbCy " << std::setw(5) << fvuCurrentTsMsbCycle[fuCurrDpbIdx];
834
837 + (fvuCurrentTsMsbCycle[fuCurrDpbIdx] * static_cast<uint64_t>(1 << stsxyter::kusLenTsMsbValBinning));
839 LOG(fatal) << "CbmMuchUnpackAlgo::processTsMsbInfo => "
840 << "Value computed from TS_MSB and TS_MSB cycle smaller than Timeslice start in TS_MSB, "
841 << "would lead to a negative value so it cannot be recovered!!!!"
842 << std::endl
844 << "TS_MSB: " << fvulCurrentTsMsb[fuCurrDpbIdx] << " Cycle: " << fvuCurrentTsMsbCycle[fuCurrDpbIdx]
845 << " Full TS_MSB: " << fulTsMsbIndexInTs[fuCurrDpbIdx] << " TS Start offset: " << fulTsStartInTsMsb;
846 }
848
849 if (fMonitor)
850 if (fMonitor->GetDebugMode()) { //also if( 1 < uMessIdx )?
851 fMonitor->FillMuchDpbRawTsMsb(fuCurrDpbIdx, fvulCurrentTsMsb[fuCurrDpbIdx]);
852 fMonitor->FillMuchDpbRawTsMsbSx(fuCurrDpbIdx, fvulCurrentTsMsb[fuCurrDpbIdx]);
853 fMonitor->FillMuchDpbRawTsMsbDpb(fuCurrDpbIdx, fvulCurrentTsMsb[fuCurrDpbIdx]);
854 }
855}
856
857// ---- refreshTsMsbFields ----
858void CbmMuchUnpackAlgo::refreshTsMsbFields(const uint32_t imslice, const size_t mstime)
859{
860 const uint32_t uTsMsbCycleHeader =
862 const uint32_t uTsMsbHeader =
863 std::floor((mstime - uTsMsbCycleHeader * (stsxyter::kulTsCycleNbBinsBinning * stsxyter::kdClockCycleNs))
865
866 LOG(debug1) << " TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << mstime << " MS Idx " << std::setw(4)
867 << imslice << " Msg Idx " << std::setw(5) << 0 << " DPB " << std::setw(2) << fuCurrDpbIdx << " Old TsMsb "
868 << std::setw(5) << fvulCurrentTsMsb[fuCurrDpbIdx] << " Old MsbCy " << std::setw(5)
869 << fvuCurrentTsMsbCycle[fuCurrDpbIdx] << " header TsMsb " << uTsMsbHeader << " New MsbCy "
870 << uTsMsbCycleHeader;
871
872 if (0 == imslice) {
873 if (uTsMsbCycleHeader != fvuCurrentTsMsbCycle[fuCurrDpbIdx])
874 LOG(debug) << " TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << mstime << " MS Idx "
875 << std::setw(4) << imslice << " Msg Idx " << std::setw(5) << 0 << " DPB " << std::setw(2)
876 << fuCurrDpbIdx << " Old TsMsb " << std::setw(5) << fvulCurrentTsMsb[fuCurrDpbIdx] << " Old MsbCy "
877 << std::setw(5) << fvuCurrentTsMsbCycle[fuCurrDpbIdx] << " New TsMsb " << uTsMsbHeader << " New MsbCy "
878 << uTsMsbCycleHeader;
879 fvuCurrentTsMsbCycle[fuCurrDpbIdx] = uTsMsbCycleHeader;
880 fvulCurrentTsMsb[fuCurrDpbIdx] = uTsMsbHeader;
881
884 + (fvuCurrentTsMsbCycle[fuCurrDpbIdx] * static_cast<uint64_t>(1 << stsxyter::kusLenTsMsbValBinning));
886 LOG(fatal) << "CbmMuchUnpackAlgo::refreshTsMsbFields => "
887 << "Value computed from TS_MSB and TS_MSB cycle smaller than Timeslice start in TS_MSB, "
888 << "would lead to a negative value so it cannot be recovered!!!!"
889 << std::endl
891 << "TS_MSB: " << fvulCurrentTsMsb[fuCurrDpbIdx] << " Cycle: " << fvuCurrentTsMsbCycle[fuCurrDpbIdx]
892 << " Full TS_MSB: " << fulTsMsbIndexInTs[fuCurrDpbIdx] << " TS Start offset: " << fulTsStartInTsMsb;
893 }
895 }
896 else if (uTsMsbCycleHeader != fvuCurrentTsMsbCycle[fuCurrDpbIdx]) {
899 LOG(debug) << " TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << mstime << " MS Idx "
900 << std::setw(4) << imslice << " Msg Idx " << std::setw(5) << 0 << " DPB " << std::setw(2)
901 << fuCurrDpbIdx << " Old TsMsb " << std::setw(5) << fvulCurrentTsMsb[fuCurrDpbIdx] << " Old MsbCy "
902 << std::setw(5) << fvuCurrentTsMsbCycle[fuCurrDpbIdx] << " New MsbCy " << uTsMsbCycleHeader;
903 }
904 else {
905 LOG(warning) << "TS MSB cycle from MS header does not match current cycle from data "
906 << "for TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << mstime << " MsInTs "
907 << std::setw(3) << imslice << " ====> " << fvuCurrentTsMsbCycle[fuCurrDpbIdx] << " (cnt) VS "
908 << uTsMsbCycleHeader << " (header)";
909 fvuCurrentTsMsbCycle[fuCurrDpbIdx] = uTsMsbCycleHeader;
910 }
911 }
912}
913
914// ---- unpack ----
915bool CbmMuchUnpackAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp, UInt_t imslice)
916{
917 auto msDescriptor = ts->descriptor(icomp, imslice);
918
922 if (fMonitor && 0 == imslice && 0 < fMsStartTime && msDescriptor.idx == ts->start_time()
923 && fMsStartTime < msDescriptor.idx) {
924 fMonitor->FillPerTimesliceCountersHistos(static_cast<double_t>(fMsStartTime) / 1e9);
925 }
926
927 //Current equipment ID, tells from which DPB the current MS is originating
928 const uint32_t uCurrentEquipmentId = msDescriptor.eq_id;
929 const uint8_t* msContent = reinterpret_cast<const uint8_t*>(ts->content(icomp, imslice));
930 const uint32_t uSize = msDescriptor.size;
931
932 fMsStartTime = msDescriptor.idx;
933 LOG(debug) << "Microslice: " << fMsStartTime << " from EqId " << std::hex << uCurrentEquipmentId << std::dec
934 << " has size: " << uSize << " (index " << imslice << ")";
935
936 if (0 == fvbMaskedComponents.size()) fvbMaskedComponents.resize(ts->num_components(), false);
937
938 //Temp holder until current equipment ID is properly filled in MS
939 const uint32_t uCurrDpbId = static_cast<uint32_t>(uCurrentEquipmentId & 0xFFFF);
940
941 if (fMonitor)
942 if (fMonitor->GetDebugMode()) {
943 const double dMsTime = (1e-9) * static_cast<double>(fMsStartTime);
944 if (icomp < fMonitor->GetMaxNbFlibLinks()) {
945 fMonitor->CreateMsComponentSizeHistos(icomp);
946 fMonitor->FillMsSize(icomp, uSize);
947 fMonitor->FillMsSizeTime(icomp, dMsTime, uSize);
948 }
949 }
950
952 auto it = fDpbIdIndexMap.find(uCurrDpbId);
953 if (it == fDpbIdIndexMap.end()) {
954 if (false == fvbMaskedComponents[icomp]) {
955 // LOG(debug) << "---------------------------------------------------------------";
956 // 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
957 // LOG(debug) << FormatMsHeaderPrintout(msDescriptor);
958 LOG(warning) << fName << "::unpack(...)::Could not find the sDPB index for AFCK id 0x" << std::hex << uCurrDpbId
959 << std::dec << " in timeslice " << fNrProcessedTs << " in microslice " << imslice << " component "
960 << icomp << "\n"
961 << "If valid this index has to be added in the STS "
962 "parameter file in the DbpIdArray field";
963 fvbMaskedComponents[icomp] = true;
964
967 if (1 == fNrProcessedTs) return true;
968 }
969 else
970 return true;
971
972 // REMARK please check experts, but I think this point can never be reached PR 072021
973 return false;
974 }
975 else
976 fuCurrDpbIdx = fDpbIdIndexMap[uCurrDpbId];
977
978 if (fMonitor) fMonitor->FillMsCntEvo(fMsStartTime);
979
980 if (0 == imslice) {
983 static_cast<uint64_t>(fTsStartTime / (stsxyter::kuHitNbTsBinsBinning * stsxyter::kdClockCycleNs));
984 }
985
986 // Check the current TS_MSb cycle and correct it if wrong
988
989 //Reset internal monitor variables for debugging info
990 if (fMonitor) {
991 if (fMonitor->GetDebugMode()) {
992 fMonitor->ResetDebugInfo();
993 }
994 }
995
996 //Main processing of MS content
997 loopMsMessages(msContent, uSize, imslice);
998
999 //Output debugging info
1000 if (fMonitor) {
1001 if (fMonitor->GetDebugMode()) {
1002 fMonitor->PrintDebugInfo(fMsStartTime, fNrProcessedTs, msDescriptor.flags, uSize);
1003 }
1004 for (auto itHit = fOutputVec.begin(); itHit != fOutputVec.end(); ++itHit) {
1005 fMonitor->FillDigisTimeInRun(itHit->GetTime());
1006 }
1007 fMonitor->FillVectorSize(ts->index(), fOutputVec.size());
1008 //fMonitor->DrawCanvases();
1009 }
1010
1011 LOG(debug2) << "Total Number of Masked Addresses " << fMaskedNoisyHitsFromCbmMuchAddress;
1012 return true;
1013}
1014
ClassImp(CbmConverterManager)
@ kMuch
Muon detection system.
MUCH unpacker algorithms.
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.
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
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
virtual std::vector< std::pair< std::string, std::shared_ptr< FairParGenericSet > > > * GetParContainerRequest(std::string geoTag, std::uint32_t runId)
Get the requested parameter containers. To be defined in the derived classes! Return the required par...
std::vector< std::vector< uint16_t > > fvvusLastAdcChan
ADC of last hit message for each channel, [ AsicIdx ][ Chan ].
bool unpack(const fles::Timeslice *ts, std::uint16_t icomp, UInt_t imslice)
Unpack a given microslice. To be implemented in the derived unpacker algos.
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.
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 µ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()
Short_t GetPadXA(UShort_t febid, UShort_t channelid)
Short_t GetPadYA(UShort_t febid, UShort_t channelid)
Short_t GetPadXB(UShort_t febid, UShort_t channelid)
Short_t GetPadYRpc(UShort_t febid, UShort_t channelid)
Short_t GetPadYB(UShort_t febid, UShort_t channelid)
static constexpr UInt_t GetNbChanPerFeb()
int32_t GetFebId(UInt_t)
Int_t ElinkIdxToFebIdx(UInt_t uElink)
Convert from eLink index to FEB Connection ( 0 to kuNbFebsPerCrob)
static constexpr UInt_t GetNbFebsPerCrob()
static constexpr UInt_t GetNbCrobsPerDpb()
Short_t GetPadXRpc(UShort_t febid, UShort_t channelid)
static constexpr UInt_t GetNbAsicsPerFeb()
static constexpr UInt_t GetNbFebsPerDpb()
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