4141namespace
4242{
4343constexpr double DigitBits = 24. ;
44- constexpr double BunchCrossingNS = 25. ;
45- constexpr int ReadoutCycleBC = 18 ;
46- constexpr int ReadoutCycleSimBC = 18 ;
47- constexpr double ReadoutCycleSeconds = ReadoutCycleBC * BunchCrossingNS * 1.e-9 ;
4844} // namespace
4945
50- void CheckBandwidth (std ::string digifile = "trkdigits.root" , std ::string inputGeom = "o2sim_geometry .root" , std ::string collContextFile = "collisioncontext.root" )
46+ void CheckBandwidth (std ::string digifile = "trkdigits.root" , std ::string inputGeom = "sgn_geometry .root" , std ::string collContextFile = "collisioncontext.root" )
5147{
5248 gStyle -> SetPalette (55 );
5349 gStyle -> SetOptStat (0 );
@@ -73,15 +69,14 @@ void CheckBandwidth(std::string digifile = "trkdigits.root", std::string inputGe
7369 latex .DrawLatex (0.04 , 0.06 , Form ("avg non-empty: %.3f collisions/ROF" , nonEmptyAverageValue ));
7470 };
7571
76- auto drawCollisionInfoBox = [](double averageValue ) {
77- const double effectiveIRRateHz = ReadoutCycleSeconds > 0. ? averageValue / ReadoutCycleSeconds : 0. ;
72+ auto drawCollisionInfoBox = [](double effectiveIRRateHz , double rofLengthBC ) {
7873 TPaveText infoBox (0.55 , 0.79 , 0.88 , 0.9 , "NDC ");
7974 infoBox .SetFillColor (0 );
8075 infoBox .SetBorderSize (1 );
8176 infoBox .SetTextAlign (12 );
8277 infoBox .SetTextSize (0.028 );
8378 infoBox .AddText (Form ("effective IR: %.3f MHz" , effectiveIRRateHz * 1.e-6 ));
84- infoBox .AddText (Form ("ROF length: %d BC" , ReadoutCycleBC ));
79+ infoBox .AddText (Form ("ROF length: %d BC" , rofLengthBC ));
8580 infoBox .DrawClone ();
8681 };
8782
@@ -168,13 +163,43 @@ void CheckBandwidth(std::string digifile = "trkdigits.root", std::string inputGe
168163 }
169164 }
170165
166+ // --- Digits ---
167+
168+ TFile * digFile = TFile ::Open (digifile .data ());
169+ TTree * digTree = (TTree * )digFile -> Get ("o2sim" );
170+ const int nDigitTreeEntries = digTree -> GetEntries ();
171+
172+ std ::vector < std ::vector < o2 ::itsmft ::Digit > * > digArr (nTotalLayers , nullptr );
173+ std ::vector < std ::vector < o2 ::itsmft ::ROFRecord > * > rofRecords (nTotalLayers , nullptr );
174+ for (int nDigitsLayer {0 }; nDigitsLayer < nTotalLayers ; ++ nDigitsLayer ) {
175+ if (!digTree -> GetBranch (Form ("TRKDigit_%i" , nDigitsLayer ))) {
176+ break ;
177+ }
178+ digTree -> SetBranchAddress (Form ("TRKDigit_%i" , nDigitsLayer ), & digArr [nDigitsLayer ]);
179+ digTree -> SetBranchAddress (Form ("TRKDigitROF_%i" , nDigitsLayer ), & rofRecords [nDigitsLayer ]);
180+ }
181+
182+ digTree -> GetEntry (0 );
183+ if (nDigitTreeEntries > 1 ) {
184+ LOG (warning ) << "Digit tree has " << nDigitTreeEntries << " entries, but this macro processes entry 0 only." ;
185+ }
186+
187+ std ::vector < unsigned int > rofLengthBC (nTotalLayers , 0u );
188+ for (int iLayer = 0 ; iLayer < nTotalLayers ; ++ iLayer ) {
189+ if (rofRecords [iLayer ]-> size () < 2 ) {
190+ LOG (fatal ) << "ROF record tree for layer " << iLayer << " has " << rofRecords [iLayer ]-> size ()
191+ << " entries, but at least 2 are expected (one per ROF + one empty at the end). Check input files." ;
192+ }
193+ rofLengthBC [iLayer ] = (* rofRecords [iLayer ])[1 ].getBCData ().bc - (* rofRecords [iLayer ])[0 ].getBCData ().bc ;
194+ }
195+
196+
171197 // --- Collision context ---
172198
173199 TFile * ccFile = TFile ::Open (collContextFile .data ());
174200 auto* digiContext = (o2 ::steer ::DigitizationContext * )ccFile -> Get ("DigitizationContext" );
175201 const o2 ::InteractionRecord firstSampledIR {0 , digiContext -> getFirstOrbitForSampling ()};
176- std ::vector < unsigned int > collisionsPerROF ;
177-
202+ std ::vector < std ::vector < unsigned int >> collisionsPerROF (nTotalLayers );
178203 for (const auto& record : digiContext -> getEventRecords ()) {
179204 auto nbc = record .differenceInBC (firstSampledIR );
180205 if (record .getTimeOffsetWrtBC () < 0. && nbc > 0 ) {
@@ -183,63 +208,48 @@ void CheckBandwidth(std::string digifile = "trkdigits.root", std::string inputGe
183208 if (nbc < 0 ) {
184209 continue ;
185210 }
186- const size_t rofID = nbc / ReadoutCycleSimBC ;
187- if (rofID >= collisionsPerROF .size ()) {
188- collisionsPerROF .resize (rofID + 1 , 0u );
211+ for (int iLayer = 0 ; iLayer < nTotalLayers ; ++ iLayer ) {
212+ if (rofLengthBC [iLayer ] == 0 ) {
213+ LOG (fatal ) << "ROF length in BC for layer " << iLayer << " is zero. Check input files." ;
214+ }
215+ const size_t rofID = nbc / rofLengthBC [iLayer ];
216+ if (rofID >= collisionsPerROF [iLayer ].size ()) {
217+ collisionsPerROF [iLayer ].resize (rofID + 1 , 0u );
218+ }
219+ ++ collisionsPerROF [iLayer ][rofID ];
189220 }
190- ++ collisionsPerROF [rofID ];
191221 }
192222
193- // --- Digits ---
194-
195- TFile * digFile = TFile ::Open (digifile .data ());
196- TTree * digTree = (TTree * )digFile -> Get ("o2sim" );
197- const int nDigitTreeEntries = digTree -> GetEntries ();
198-
199- std ::vector < o2 ::itsmft ::Digit > * digArr = nullptr ;
200- std ::vector < o2 ::itsmft ::ROFRecord > * rofRecords = nullptr ;
201- digTree -> SetBranchAddress ("TRKDigit" , & digArr );
202- digTree -> SetBranchAddress ("TRKDigitROF" , & rofRecords );
203-
204- digTree -> GetEntry (0 );
205- if (nDigitTreeEntries > 1 ) {
206- LOG (warning ) << "Digit tree has " << nDigitTreeEntries << " entries, but this macro processes entry 0 only." ;
207- }
208-
209- const int nROFRec = (int )rofRecords -> size ();
210- if (nROFRec != (int )collisionsPerROF .size ()) {
223+ const int nROFRec = (int )rofRecords [0 ]-> size ();
224+ if (nROFRec != (int )collisionsPerROF [0 ].size ()) {
211225 LOG (fatal ) << "Mismatch between number of ROF records in digit tree (" << nROFRec
212- << ") and number of ROFs computed from collisioncontext.root (" << collisionsPerROF .size ()
226+ << ") and number of ROFs computed from collisioncontext.root (" << collisionsPerROF [ 0 ] .size ()
213227 << "). Check input files." ;
214228 }
215229
216230 // --- Accumulate per-chip digit counts across all ROFs ---
217231
218- const double rofNorm = nROFRec > 0 ? 1. / nROFRec : 0. ;
219- const double bitsToGbps = ReadoutCycleSeconds > 0. ? DigitBits / ReadoutCycleSeconds / 1.e9 : 0. ;
220232
221233 std ::vector < unsigned long long> digitsPerChip (nChips , 0ull ) ;
222234 std ::vector < unsigned int > maxDigitsPerROFPerChip (nChips , 0u );
223235 std ::vector < unsigned int > digitsInCurrentROFPerChip (nChips , 0u );
224236
225- for (unsigned int iROF = 0 ; iROF < rofRecords -> size () ; ++ iROF ) {
237+ for (unsigned int iROF = 0 ; iROF < ( unsigned int ) nROFRec ; ++ iROF ) {
226238 std ::vector < int > touchedChips ;
227- const unsigned int rofStart = ( * rofRecords )[ iROF ]. getFirstEntry ();
228- const unsigned int rofEnd = rofStart + (* rofRecords )[iROF ].getNEntries ();
229-
230- for (unsigned int iDigit = rofStart ; iDigit < rofEnd ; ++ iDigit ) {
231- if ( iDigit % 1000 == 0 ) {
232- std :: cout << "Reading digit " << iDigit << " / " << digArr -> size () << "\r" << std :: flush ;
233- }
234- const int chipID = ( * digArr )[ iDigit ]. getChipIndex ();
235- if (chipGeom [chipID ]. disk != -1 ) {
236- continue ;
237- }
238- if ( digitsInCurrentROFPerChip [chipID ] == 0 ) {
239- touchedChips . push_back ( chipID ) ;
239+ for ( int iLayer = 0 ; iLayer < nTotalLayers ; ++ iLayer ) {
240+ const unsigned int rofStart = (* rofRecords [ iLayer ] )[iROF ].getFirstEntry ();
241+ const unsigned int rofEnd = rofStart + ( * rofRecords [ iLayer ])[ iROF ]. getNEntries ();
242+ for (unsigned int iDigit = rofStart ; iDigit < rofEnd ; ++ iDigit ) {
243+ const int chipID = ( * digArr [ iLayer ])[ iDigit ]. getChipIndex ();
244+ if ( chipGeom [ chipID ]. disk != -1 ) {
245+ continue ;
246+ }
247+ if (digitsInCurrentROFPerChip [chipID ] == 0 ) {
248+ touchedChips . push_back ( chipID ) ;
249+ }
250+ ++ digitsPerChip [chipID ];
251+ ++ digitsInCurrentROFPerChip [ chipID ] ;
240252 }
241- ++ digitsPerChip [chipID ];
242- ++ digitsInCurrentROFPerChip [chipID ];
243253 }
244254
245255 for (const int chipID : touchedChips ) {
@@ -273,19 +283,21 @@ void CheckBandwidth(std::string digifile = "trkdigits.root", std::string inputGe
273283 // digitsInCurrentROFPerChip is all zeros after the first scan — reuse it here.
274284 {
275285 std ::vector < int > touchedChips ;
276- for (unsigned int iROF = 0 ; iROF < rofRecords -> size () ; ++ iROF ) {
286+ for (unsigned int iROF = 0 ; iROF < ( unsigned int ) nROFRec ; ++ iROF ) {
277287 touchedChips .clear ();
278- const unsigned int rofStart = (* rofRecords )[iROF ].getFirstEntry ();
279- const unsigned int rofEnd = rofStart + (* rofRecords )[iROF ].getNEntries ();
280- for (unsigned int iDigit = rofStart ; iDigit < rofEnd ; ++ iDigit ) {
281- const int chipID = (* digArr )[iDigit ].getChipIndex ();
282- if (chipGeom [chipID ].disk != -1 ) {
283- continue ;
288+ for (int iLayer = 0 ; iLayer < nTotalLayers ; ++ iLayer ) {
289+ const unsigned int rofStart = (* rofRecords [iLayer ])[iROF ].getFirstEntry ();
290+ const unsigned int rofEnd = rofStart + (* rofRecords [iLayer ])[iROF ].getNEntries ();
291+ for (unsigned int iDigit = rofStart ; iDigit < rofEnd ; ++ iDigit ) {
292+ const int chipID = (* digArr [iLayer ])[iDigit ].getChipIndex ();
293+ if (chipGeom [chipID ].disk != -1 ) {
294+ continue ;
295+ }
296+ if (digitsInCurrentROFPerChip [chipID ] == 0 ) {
297+ touchedChips .push_back (chipID );
298+ }
299+ ++ digitsInCurrentROFPerChip [chipID ];
284300 }
285- if (digitsInCurrentROFPerChip [chipID ] == 0 ) {
286- touchedChips .push_back (chipID );
287- }
288- ++ digitsInCurrentROFPerChip [chipID ];
289301 }
290302 for (const int chipID : touchedChips ) {
291303 const int l = chipGeom [chipID ].globalLayer ;
@@ -321,7 +333,7 @@ void CheckBandwidth(std::string digifile = "trkdigits.root", std::string inputGe
321333 continue ;
322334 }
323335 const int l = g .globalLayer ;
324- const double avgDigits = digitsPerChip [chipID ] * rofNorm ;
336+ const double avgDigits = digitsPerChip [chipID ] / collisionsPerROF [ l ]. size () ;
325337 const double maxDigits = (double )maxDigitsPerROFPerChip [chipID ];
326338 layerStats [l ].avgDigitsPerROF += avgDigits ;
327339 layerStats [l ].avgMaxDigitsPerROF += maxDigits ;
@@ -334,37 +346,50 @@ void CheckBandwidth(std::string digifile = "trkdigits.root", std::string inputGe
334346 layerStats [l ].avgDigitsPerROF *= norm ;
335347 layerStats [l ].avgMaxDigitsPerROF *= norm ;
336348 }
337- layerStats [l ].avgBandwidthGbps = layerStats [l ].avgDigitsPerROF * bitsToGbps ;
338- layerStats [l ].peakBandwidthGbps = layerStats [l ].peakAvgDigitsPerROF * bitsToGbps ;
349+ layerStats [l ].avgBandwidthGbps = layerStats [l ].avgDigitsPerROF * DigitBits / rofLengthBC [ l ] / o2 :: constants :: lhc :: LHCBunchSpacingNS * 1.e9 ;
350+ layerStats [l ].peakBandwidthGbps = layerStats [l ].peakAvgDigitsPerROF * DigitBits / rofLengthBC [ l ] / o2 :: constants :: lhc :: LHCBunchSpacingNS * 1.e9 ;
339351 }
340352
341353 // --- Collision plots ---
342354
343355 if (nROFRec > 0 ) {
344- auto* hCollisionsPerROF = new TH1D ("h_collisions_per_rof" , "Collisions per ROF;ROF id;N collisions" ,
345- nROFRec , -0.5 , nROFRec - 0.5 );
346- double totalCollisionsPerROF = 0. ;
347- double peakCollisionsPerROF = 0. ;
348- int nNonEmptyROFs = 0 ;
349-
350- for (int rofID = 0 ; rofID < nROFRec ; ++ rofID ) {
351- const double nColl = collisionsPerROF [rofID ];
352- hCollisionsPerROF -> SetBinContent (rofID + 1 , nColl );
353- totalCollisionsPerROF += nColl ;
354- peakCollisionsPerROF = std ::max (peakCollisionsPerROF , nColl );
355- if (nColl > 0. ) {
356- ++ nNonEmptyROFs ;
356+ std ::vector < double > totalCollisionsPerROF (nTotalLayers , 0. );
357+ std ::vector < double > peakCollisionsPerROF (nTotalLayers , 0. );
358+ std ::vector < int > nNonEmptyROFs (nTotalLayers , 0 );
359+ std ::vector < TH1D * > hCollisionsPerROFPerLayer (nTotalLayers , nullptr );
360+
361+ for (int iLayer = 0 ; iLayer < nTotalLayers ; ++ iLayer ) {
362+ hCollisionsPerROFPerLayer [iLayer ] = new TH1D (Form ("h_collisions_per_rof_layer%d" , iLayer ),
363+ Form ("Layer %d;ROF id;N collisions" , iLayer ),
364+ nROFRec , -0.5 , nROFRec - 0.5 );
365+ for (int rofID = 0 ; rofID < nROFRec ; ++ rofID ) {
366+ const double nColl = collisionsPerROF [iLayer ][rofID ];
367+ hCollisionsPerROFPerLayer [iLayer ]-> SetBinContent (rofID + 1 , nColl );
368+ totalCollisionsPerROF [iLayer ] += nColl ;
369+ peakCollisionsPerROF [iLayer ] = std ::max (peakCollisionsPerROF [iLayer ], nColl );
370+ if (nColl > 0. ) {
371+ ++ nNonEmptyROFs [iLayer ];
372+ }
357373 }
358374 }
359375
360- const double avgCollisionsPerROF = totalCollisionsPerROF / nROFRec ;
361- auto* canvCollisionsPerROF = new TCanvas ("canvCollisionsPerROF" , "Collisions per ROF" , 1050 , 1050 );
362- canvCollisionsPerROF -> SetTopMargin (0.08 );
363- hCollisionsPerROF -> Draw ("hist" );
364- drawCollisionSummary (avgCollisionsPerROF ,
365- nNonEmptyROFs > 0 ? totalCollisionsPerROF / nNonEmptyROFs : 0. ,
366- peakCollisionsPerROF );
367- drawCollisionInfoBox (avgCollisionsPerROF );
376+ const int nCols = std ::max (1 , (int )std ::ceil (std ::sqrt ((double )nTotalLayers )));
377+ const int nRows = (nTotalLayers + nCols - 1 ) / nCols ;
378+ auto* canvCollisionsPerROF = new TCanvas ("canvCollisionsPerROF" , "Collisions per ROF" , 350 * nCols , 300 * nRows );
379+ canvCollisionsPerROF -> Divide (nCols , nRows );
380+ for (int iLayer = 0 ; iLayer < nTotalLayers ; ++ iLayer ) {
381+ canvCollisionsPerROF -> cd (iLayer + 1 );
382+ gPad -> SetTopMargin (0.10 );
383+ gPad -> SetBottomMargin (0.14 );
384+ gPad -> SetLeftMargin (0.14 );
385+ hCollisionsPerROFPerLayer [iLayer ]-> Draw ("hist" );
386+ const double avgCollisionsPerROF = totalCollisionsPerROF [iLayer ] / collisionsPerROF [iLayer ].size ();
387+ drawCollisionSummary (avgCollisionsPerROF ,
388+ nNonEmptyROFs [iLayer ] > 0 ? totalCollisionsPerROF [iLayer ] / nNonEmptyROFs [iLayer ] : 0. ,
389+ peakCollisionsPerROF [iLayer ]);
390+ const double effectiveIRRateHz = avgCollisionsPerROF / rofLengthBC [iLayer ] / o2 ::constants ::lhc ::LHCBunchSpacingNS * 1.e9 ;
391+ drawCollisionInfoBox (effectiveIRRateHz , rofLengthBC [iLayer ]);
392+ }
368393 appendCanvasToPdf (canvCollisionsPerROF );
369394 }
370395
@@ -405,9 +430,9 @@ void CheckBandwidth(std::string digifile = "trkdigits.root", std::string inputGe
405430 if (g .petal < 0 || g .petal >= nVDPetals ) {
406431 continue ;
407432 }
408- const double avgDigits = digitsPerChip [chipID ] * rofNorm ;
433+ const double avgDigits = double ( digitsPerChip [chipID ]) / collisionsPerROF [ g . globalLayer ]. size () ;
409434 const double maxDigits = (double )maxDigitsPerROFPerChip [chipID ];
410- const double bandwidth = avgDigits * bitsToGbps ;
435+ const double bandwidth = avgDigits * DigitBits / rofLengthBC [ g . globalLayer ] / o2 :: constants :: lhc :: LHCBunchSpacingNS * 1.e9 ;
411436
412437 hVDDigitsPerROF -> SetBinContent (g .petal + 1 , g .localLayer + 1 , avgDigits );
413438 hVDMaxDigitsPerROF -> SetBinContent (g .petal + 1 , g .localLayer + 1 , maxDigits );
@@ -483,12 +508,12 @@ void CheckBandwidth(std::string digifile = "trkdigits.root", std::string inputGe
483508 continue ;
484509 }
485510 const double staveBinX = g .stave + (g .halfStave + 0.5 ) / nHalfStaves - 0.5 ;
486- const double avgDigits = digitsPerChip [chipID ] * rofNorm ;
511+ const double avgDigits = double ( digitsPerChip [chipID ]) / collisionsPerROF [ g . globalLayer ]. size () ;
487512 const double maxDigits = (double )maxDigitsPerROFPerChip [chipID ];
488513
489514 hDigitsPerROF -> Fill (staveBinX , sensorID , avgDigits );
490515 hMaxDigitsPerROF -> Fill (staveBinX , sensorID , maxDigits );
491- hBandwidth -> Fill (staveBinX , sensorID , avgDigits * bitsToGbps );
516+ hBandwidth -> Fill (staveBinX , sensorID , avgDigits * DigitBits / rofLengthBC [ g . globalLayer ] / o2 :: constants :: lhc :: LHCBunchSpacingNS * 1.e9 );
492517 }
493518
494519 const auto& ls = layerStats [outputLayer ];
0 commit comments