31 mIsContinuous = sopt.continuous;
34 LOG(fatal) <<
"Missing ModuleConfig configuration object";
39 LOG(fatal) <<
"Missing SimCondition configuration object";
44 LOG(fatal) <<
"Bunch crossing map is not initialized";
49 LOG(warning) <<
"Bunch crossing map has zero clean empty bunches";
54 std::string outd = outDir;
55 if (outd.back() !=
'/') {
59 mLinkID = uint32_t(0);
62 mEndPointID = uint32_t(0);
66 for (
int ilink = 0; ilink <
NLinks; ilink++) {
67 uint64_t FeeID = uint64_t(ilink);
69 if (mFileFor !=
"all") {
70 outFileLink += fmt::format(
"_{}", mFLP);
71 if (mFileFor !=
"flp") {
72 outFileLink += fmt::format(
"_cru{}_{}", mCruID, mEndPointID);
73 if (mFileFor !=
"cruendpoint") {
74 outFileLink += fmt::format(
"_lnk{}_feeid{}", ilink, FeeID);
75 if (mFileFor !=
"link") {
76 LOG(fatal) <<
"Not supported output file splitting: " << mFileFor;
77 throw std::runtime_error(
"invalid option provided for file grouping");
82 outFileLink +=
".raw";
83 mWriter.
registerLink(FeeID, mCruID, mLinkID, mEndPointID, outFileLink);
86 std::unique_ptr<TFile> digiFile(TFile::Open(fileDigitsName.c_str()));
87 if (!digiFile || digiFile->IsZombie()) {
88 LOG(fatal) <<
"Failed to open input digits file " << fileDigitsName;
92 TTree* digiTree = (TTree*)digiFile->Get(
"o2sim");
94 LOG(fatal) <<
"Failed to get digits tree";
98 if (digiTree->GetBranch(
"ZDCDigitBC")) {
99 digiTree->SetBranchAddress(
"ZDCDigitBC", &mzdcBCDataPtr);
101 LOG(fatal) <<
"Branch ZDCDigitBC is missing";
105 if (digiTree->GetBranch(
"ZDCDigitCh")) {
106 digiTree->SetBranchAddress(
"ZDCDigitCh", &mzdcChDataPtr);
108 LOG(fatal) <<
"Branch ZDCDigitCh is missing";
112 if (digiTree->GetBranch(
"ZDCDigitOrbit")) {
113 digiTree->SetBranchAddress(
"ZDCDigitOrbit", &mzdcPedDataPtr);
115 LOG(fatal) <<
"Branch ZDCDigitOrbit is missing";
119 if (digiTree->GetBranchStatus(
"ZDCDigitLabels")) {
120 digiTree->SetBranchStatus(
"ZDCDigitLabel*", 0);
130 for (
int ient = 0; ient < digiTree->GetEntries(); ient++) {
131 digiTree->GetEntry(ient);
132 mNbc = mzdcBCData.size();
133 if (mVerbosity > 0) {
134 LOG(info) <<
"Entry " << ient <<
": processing " << mNbc <<
" BCs stored";
136 for (
int ibc = 0; ibc < mNbc; ibc++) {
137 mBCD = mzdcBCData[ibc];
141 if (ibc == (mNbc - 1)) {
143 if (mzdcBCData[ibc].
ir.
bc != 3563) {
144 if (mVerbosity > 1) {
145 LOG(info) <<
"Closing last orbit " << mzdcBCData[ibc].ir.orbit;
147 insertLastBunch(ibc, mzdcBCData[ibc].
ir.
orbit);
152 auto this_orbit = mzdcBCData[ibc].ir.orbit;
153 auto next_orbit = mzdcBCData[ibc + 1].ir.orbit;
155 if (mzdcBCData[ibc].
ir.
bc == 3563) {
156 this_orbit = this_orbit + 1;
160 if (mVerbosity > 1) {
161 LOG(info) <<
"Inserting last bunch for orbit " <<
orbit;
163 insertLastBunch(ibc,
orbit);
169 LOG(info) <<
"Entry " << ient <<
" Converted BCs: " << mNbc <<
" + added@3563:" << nBCadd <<
" = " << mNbc + nBCadd;
175void Digits2Raw::setTriggerMask()
178 mPrintTriggerMask =
"";
179 for (int32_t im = 0; im <
NModules; im++) {
181 mPrintTriggerMask +=
" ";
184 mPrintTriggerMask +=
"[";
186 if (mModuleConfig->
modules[im].trigChannel[ic]) {
188 mTriggerMask = mTriggerMask | tmask;
189 mPrintTriggerMask +=
"T";
191 mPrintTriggerMask +=
" ";
194 mPrintTriggerMask +=
"]";
197 printf(
"Trigger mask for module %d 0123 %s%s%s%s\n", im,
198 mytmask & 0x1 ?
"T" :
"N",
199 mytmask & 0x2 ?
"T" :
"N",
200 mytmask & 0x4 ?
"T" :
"N",
201 mytmask & 0x8 ?
"T" :
"N");
204 printf(
"trigger_mask=0x%08x %s", mTriggerMask, mPrintTriggerMask.data());
208inline void Digits2Raw::resetSums(uint32_t
orbit)
210 for (int32_t im = 0; im <
NModules; im++) {
212 mScalers[im][ic] = 0;
217 mLatestOrbit =
orbit;
222inline void Digits2Raw::updatePedestalReference(
int bc)
228 for (; io < mzdcPedData.size(); io++) {
234 if (io == mzdcPedData.size()) {
235 LOG(fatal) <<
"Cannot find orbit";
237 for (int32_t im = 0; im <
NModules; im++) {
240 auto id = mModuleConfig->
modules[im].channelID[ic];
241 mPed[im][ic] = *((uint16_t*)&mzdcPedData[io].
data[
id]);
244 }
else if (mEmpty[
bc] > 0 && mEmpty[
bc] != mLastNEmpty) {
248 for (int32_t im = 0; im <
NModules; im++) {
251 auto id = mModuleConfig->
modules[im].channelID[ic];
252 auto base_m = mSimCondition->
channels[
id].pedestal;
253 auto base_s = mSimCondition->
channels[
id].pedestalFluct;
254 auto base_n = mSimCondition->
channels[
id].pedestalNoise;
255 double deltan = mEmpty[
bc] - mLastNEmpty;
259 mSumPed[im][ic] += gRandom->Gaus(12. * deltan * base_m, 12. * k * base_s * TMath::Sqrt(deltan / k));
261 mSumPed[im][ic] += gRandom->Gaus(0, base_n * TMath::Sqrt(12. * deltan));
262 double myped = mSumPed[im][ic] / double(mEmpty[
bc]) / 12.;
264 int16_t theped = myped;
266 if (myped < -32768) {
272 mPed[im][ic] = *((uint16_t*)&theped);
275 mLastNEmpty = mEmpty[
bc];
280inline void Digits2Raw::resetOutputStructure(uint16_t
bc, uint32_t
orbit,
bool is_dummy)
283 for (uint32_t im = 0; im <
NModules; im++) {
287 mZDC.
data[im][ic].
w[0][1] = 0;
288 mZDC.
data[im][ic].
w[0][2] = 0;
289 mZDC.
data[im][ic].
w[0][3] = 0;
291 mZDC.
data[im][ic].
w[1][1] = 0;
292 mZDC.
data[im][ic].
w[1][2] = 0;
293 mZDC.
data[im][ic].
w[1][3] = 0;
295 mZDC.
data[im][ic].
w[2][1] = 0;
296 mZDC.
data[im][ic].
w[2][2] = 0;
297 mZDC.
data[im][ic].
w[2][3] = 0;
299 mZDC.
data[im][ic].
f.board = im;
300 mZDC.
data[im][ic].
f.ch = ic;
308 mZDC.
data[im][ic].
f.Hit = 1;
311 mZDC.
data[im][ic].
f.hits = mScalers[im][ic];
312 mZDC.
data[im][ic].
f.offset = mPed[im][ic];
318inline void Digits2Raw::assignTriggerBits(
int ibc, uint16_t
bc, uint32_t
orbit,
bool is_dummy)
325 for (uint32_t im = 0; im <
NModules; im++) {
326 triggers.
w = mzdcBCData[ibc].moduleTriggers[im];
328 mZDC.
data[im][ic].
f.Alice_0 = triggers.
f.Alice_0;
329 mZDC.
data[im][ic].
f.Alice_1 = triggers.
f.Alice_1;
330 mZDC.
data[im][ic].
f.Alice_2 = triggers.
f.Alice_2;
331 mZDC.
data[im][ic].
f.Alice_3 = triggers.
f.Alice_3;
332 mZDC.
data[im][ic].
f.Auto_m = triggers.
f.Auto_m;
333 mZDC.
data[im][ic].
f.Auto_0 = triggers.
f.Auto_0;
334 mZDC.
data[im][ic].
f.Auto_1 = triggers.
f.Auto_1;
335 mZDC.
data[im][ic].
f.Auto_2 = triggers.
f.Auto_2;
336 mZDC.
data[im][ic].
f.Auto_3 = triggers.
f.Auto_3;
343void Digits2Raw::insertLastBunch(
int ibc, uint32_t
orbit)
352 if (
orbit != mLatestOrbit) {
356 updatePedestalReference(
bc);
359 resetOutputStructure(
bc,
orbit,
true);
362 assignTriggerBits(ibc,
bc,
orbit,
true);
365 for (int32_t im = 0; im <
NModules; im++) {
367 if (mModuleConfig->
modules[im].readChannel[ic]) {
368 auto id = mModuleConfig->
modules[im].channelID[ic];
369 auto base_m = mSimCondition->
channels[
id].pedestal;
370 auto base_s = mSimCondition->
channels[
id].pedestalFluct;
371 auto base_n = mSimCondition->
channels[
id].pedestalNoise;
372 double base = gRandom->Gaus(base_m, base_s);
373 double val = base + gRandom->Gaus(0, base_n);
375 val = base + gRandom->Gaus(0, base_n);
377 val = base + gRandom->Gaus(0, base_n);
379 val = base + gRandom->Gaus(0, base_n);
381 val = base + gRandom->Gaus(0, base_n);
383 val = base + gRandom->Gaus(0, base_n);
385 val = base + gRandom->Gaus(0, base_n);
387 val = base + gRandom->Gaus(0, base_n);
389 val = base + gRandom->Gaus(0, base_n);
391 val = base + gRandom->Gaus(0, base_n);
393 val = base + gRandom->Gaus(0, base_n);
395 val = base + gRandom->Gaus(0, base_n);
403void Digits2Raw::convertDigits(
int ibc)
412 if (
orbit != mLatestOrbit) {
416 updatePedestalReference(
bc);
419 resetOutputStructure(
bc,
orbit,
false);
422 assignTriggerBits(ibc,
bc,
orbit,
false);
424 if (mVerbosity > 0) {
425 mBCD.
print(mTriggerMask);
428 int chEnt = mBCD.
ref.getFirstEntry();
429 for (
int ic = 0; ic < mBCD.
ref.getEntries(); ic++) {
430 const auto& chd = mzdcChData[chEnt++];
431 if (mVerbosity > 0) {
439 for (int32_t im = 0; im <
NModules; im++) {
441 if (mModuleConfig->
modules[im].channelID[ic] == chd.id &&
442 mModuleConfig->
modules[im].readChannel[ic]) {
444 mZDC.
data[im][ic].
f.s00 = chd.data[is++];
445 mZDC.
data[im][ic].
f.s01 = chd.data[is++];
446 mZDC.
data[im][ic].
f.s02 = chd.data[is++];
447 mZDC.
data[im][ic].
f.s03 = chd.data[is++];
448 mZDC.
data[im][ic].
f.s04 = chd.data[is++];
449 mZDC.
data[im][ic].
f.s05 = chd.data[is++];
450 mZDC.
data[im][ic].
f.s06 = chd.data[is++];
451 mZDC.
data[im][ic].
f.s07 = chd.data[is++];
452 mZDC.
data[im][ic].
f.s08 = chd.data[is++];
453 mZDC.
data[im][ic].
f.s09 = chd.data[is++];
454 mZDC.
data[im][ic].
f.s10 = chd.data[is++];
455 mZDC.
data[im][ic].
f.s11 = chd.data[is++];
464void Digits2Raw::writeDigits()
466 constexpr static int data_size =
sizeof(uint32_t) *
NWPerGBTW;
467 constexpr static gsl::span<char>
empty;
474 bool TM = mZDC.
data[im][0].
f.Auto_m;
475 bool T0 = mZDC.
data[im][0].
f.Auto_0;
476 bool T1 = mZDC.
data[im][0].
f.Auto_1;
477 bool T2 = mZDC.
data[im][0].
f.Auto_2;
478 bool T3 = mZDC.
data[im][0].
f.Auto_3;
479 bool A0 = mZDC.
data[im][0].
f.Alice_0;
480 bool A1 = mZDC.
data[im][0].
f.Alice_1;
481 bool A2 = mZDC.
data[im][0].
f.Alice_2;
482 bool A3 = mZDC.
data[im][0].
f.Alice_3;
483 bool tcond_continuous = T0 || T1;
484 bool tcond_triggered = A0 || A1 || (A2 && (T0 || TM)) || (A3 && T0);
485 bool tcond_last = mZDC.
data[im][0].
f.bc == 3563;
487 bool addedChData[
NChPerModule] = {
false,
false,
false,
false};
488 if (tcond_triggered || (mIsContinuous && tcond_continuous) || (mZDC.
data[im][0].
f.bc == 3563)) {
490 uint64_t
FeeID = 2 * im + ic / 2;
491 if (mModuleConfig->
modules[im].readChannel[ic]) {
493 if (mEnablePadding) {
494 gsl::span<char> payload{
reinterpret_cast<char*
>(&mZDC.
data[im][ic].
w[iw][0]), data_size};
495 mWriter.
addData(FeeID, mCruID, mLinkID, mEndPointID,
ir, payload);
497 gsl::span<char> payload{
reinterpret_cast<char*
>(&mZDC.
data[im][ic].
w[iw][0]),
PayloadPerGBTW};
499 mWriter.
addData(FeeID, mCruID, mLinkID, mEndPointID,
ir, payload);
502 addedChData[ic] =
true;
507 if (addedChData[0] ==
false && addedChData[1] ==
false) {
508 uint64_t
FeeID = 2 * im;
511 if (addedChData[2] ==
false && addedChData[3] ==
false) {
512 uint64_t
FeeID = 2 * im + 1;
515 if (mVerbosity > 1) {
516 if (tcond_continuous) {
517 printf(
"M%d Cont. T0=%d || T1=%d\n", im, T0, T1);
519 if (tcond_triggered) {
520 printf(
"M%d Trig. %s A0=%d || A1=%d || (A2=%d && (T0=%d || TM=%d))=%d || (A3=%d && T0=%d )=%d\n", im, mIsContinuous ?
"CM" :
"TM", A0, A1, A2, T0, TM, A2 && (T0 || TM), A3, T0, A3 && T0);
522 if (mZDC.
data[im][0].
f.bc == 3563) {
523 printf(
"M%d is last BC\n", im);
525 if (tcond_triggered || (mIsContinuous && tcond_continuous) || (mZDC.
data[im][0].
f.bc == 3563)) {
527 if (mModuleConfig->
modules[im].readChannel[ic]) {
534 if (mVerbosity > 2) {
535 printf(
"orbit %9u bc %4u M%d SKIP\n", mZDC.
data[im][0].
f.orbit, mZDC.
data[im][0].
f.bc, im);
545 if (word ==
nullptr) {
553 unsigned __int128
val = word[2];
558 static uint32_t last_orbit = 0, last_bc = 0;
561 ULong64_t msb =
val >> 64;
562 uint32_t
a = word[0];
563 uint32_t
b = word[1];
564 uint16_t
c = *((uint16_t*)&word[2]);
566 if ((
a & 0x3) == 0) {
567 uint32_t myorbit = (
val >> 48) & 0xffffffff;
568 uint32_t mybc = (
val >> 36) & 0xfff;
569 if (myorbit != last_orbit || mybc != last_bc) {
570 printf(
"Orbit %9u bc %4u\n", myorbit, mybc);
571 last_orbit = myorbit;
574 printf(
"%04x %08x %08x ",
c,
b,
a);
575 uint32_t hits = (
val >> 24) & 0xfff;
576 word16.uns = (lsb >> 8) & 0xffff;
578 uint32_t board = (lsb >> 2) & 0xf;
579 uint32_t ch = (lsb >> 6) & 0x3;
580 printf(
"orbit %9u bc %4u hits %4u offset %+6i Board %2u Ch %1u", myorbit, mybc, hits, word16.sig, board, ch);
583 printf(
" ERROR with board");
586 printf(
" ERROR with ch");
589 auto id = moduleConfig->
modules[board].channelID[ch];
593 printf(
" error with ch id");
596 }
else if ((
a & 0x3) == 1) {
597 printf(
"%04x %08x %08x ",
c,
b,
a);
598 printf(
" %s %s %s %s ",
a & 0x10 ?
"A0" :
" ",
a & 0x20 ?
"A1" :
" ",
a & 0x40 ?
"A2" :
" ",
a & 0x80 ?
"A3" :
" ");
602 for (int32_t
i = 0;
i < 6;
i++) {
609 printf(
" %5d %5d %5d %5d %5d %5d%s%s", s[0], s[1], s[2], s[3], s[4], s[5], (
a & 0x4) ?
" DLOSS" :
"", (
a & 0x8) ?
" ERROR" :
"");
610 }
else if ((
a & 0x3) == 2) {
611 printf(
"%04x %08x %08x ",
c,
b,
a);
612 printf(
"%s %s %s %s %s %s ",
a & 0x4 ?
"H" :
" ",
a & 0x8 ?
"TM" :
" ",
a & 0x10 ?
"T0" :
" ",
a & 0x20 ?
"T1" :
" ",
a & 0x40 ?
"T2" :
" ",
a & 0x80 ?
"T3" :
" ");
616 for (int32_t
i = 0;
i < 6;
i++) {
623 printf(
" %5d %5d %5d %5d %5d %5d", s[0], s[1], s[2], s[3], s[4], s[5]);
624 }
else if ((
a & 0x3) == 3) {
625 printf(
"%04x %08x %08x ",
c,
b,
a);
643 for (
int i = 0;
i < mModuleConfig->
NWMap;
i++) {
645 for (
int j = 0;
j < 64;
j++) {
648 mEmpty[ib] = mNEmpty;
650 mEmpty[ib] = mNEmpty;
659 for (int32_t ib = 0; ib < LHCMaxBunches; ib++) {
667 if (bunchPattern[mb] || bunchPattern[m1] || bunchPattern[ib] || bunchPattern[
p1] || bunchPattern[
p2] || bunchPattern[p3]) {
668 mEmpty[ib] = mNEmpty;
671 mEmpty[ib] = mNEmpty;
680 if (mNEmpty != 0 && mNEmpty != mModuleConfig->
nBunchAverage) {
681 LOG(fatal) <<
"Mismatch with empty map mNEmpty = " << mNEmpty <<
" nBunchAverage = " << mModuleConfig->
nBunchAverage;
683 LOG(info) <<
"There are " << mNEmpty <<
" clean empty bunches";
constexpr int p1()
constexpr to accelerate the coordinates changing
converts digits to raw format
static const ZDCSimParam & Instance()
void addData(uint16_t feeid, uint16_t cru, uint8_t lnk, uint8_t endpoint, const IR &ir, const gsl::span< char > data, bool preformatted=false, uint32_t trigger=0, uint32_t detField=0)
LinkData & registerLink(uint16_t fee, uint16_t cru, uint8_t link, uint8_t endpoint, std::string_view outFileName)
void processDigits(const std::string &outDir, const std::string &fileDigitsName)
Prepare list of clean empty bunches for baseline evaluation.
void emptyBunches(std::bitset< 3564 > &bunchPattern)
static void print_gbt_word(const uint32_t *word, const ModuleConfig *moduleConfig=nullptr)
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
constexpr int LHCMaxBunches
constexpr int FeeID[2]
FEE_ID in RDH.
constexpr int NChPerModule
constexpr unsigned short Id_w1
constexpr int PayloadPerGBTW
constexpr unsigned short Id_w2
constexpr unsigned short Id_w0
constexpr std::string_view ChannelNames[]
std::string to_string(gsl::span< T, Size > span)
uint16_t bc
bunch crossing ID of interaction
static std::string concat_string(Ts const &... ts)
o2::dataformats::RangeRefComp< 6 > ref
void print(uint32_t triggerMask=0, int diff=0) const
EventChData data[NModules][NChPerModule]
std::array< uint64_t, NWMap > emptyMap
static constexpr int NWMap
std::array< Module, MaxNModules > modules
std::array< ChannelSimCondition, NChannels > channels
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)
UInt_t w[NWPerBc][NWPerGBTW]
struct ModuleTriggerMap f