@@ -225,7 +225,7 @@ class BcSelectionModule
225225 // first bc of the first orbit
226226 bcSOR = static_cast <int64_t >((sorTimestamp * 1000 - orbitResetMUS) / o2::constants::lhc::LHCOrbitMUS) * nBCsPerOrbit;
227227 // duration of TF in bcs
228- nBCsPerTF = 32 ; // hard-coded for Run3 MC (no info from ccdb at the moment)
228+ nBCsPerTF = 32 * nBCsPerOrbit ; // hard-coded 32 orbits per TF for Run3 MC (no info from ccdb at the moment)
229229 } else {
230230 auto runInfo = (!isMC) ? o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo (o2::ccdb::BasicCCDBManager::instance (), run)
231231 : o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo (o2::ccdb::BasicCCDBManager::instance (), run, strLPMProductionTag);
@@ -626,7 +626,6 @@ class EventSelectionModule
626626 int run3min = 500000 ;
627627 int lastRun = -1 ; // last run number (needed to access ccdb only if run!=lastRun)
628628 std::bitset<nBCsPerOrbit> bcPatternB; // bc pattern of colliding bunches
629- std::vector<int > bcsPattern; // pattern of colliding BCs
630629
631630 int64_t bcSOR = -1 ; // global bc of the start of the first orbit
632631 int64_t nBCsPerTF = -1 ; // duration of TF in bcs, should be 128*3564 or 32*3564
@@ -640,18 +639,17 @@ class EventSelectionModule
640639 std::vector<float > diffVzParMean; // parameterization for mean of diff vZ by FT0 vs by tracks
641640 std::vector<float > diffVzParSigma; // parameterization for stddev of diff vZ by FT0 vs by tracks
642641
643- int32_t findClosest (const int64_t globalBC, const std::map<int64_t , int32_t >& bcs)
642+ // first colliding BC (in ascending order) within +/- maxDiff of localBC, or -1 if none
643+ int32_t findBCinPattern (int32_t localBC, int32_t maxDiff = 20 ) const // o2-linter: disable=magic-number (max BC difference to match pattern)
644644 {
645- auto it = bcs.lower_bound (globalBC);
646- int64_t bc1 = it->first ;
647- int32_t index1 = it->second ;
648- if (it != bcs.begin ())
649- --it;
650- int64_t bc2 = it->first ;
651- int32_t index2 = it->second ;
652- int64_t dbc1 = std::abs (bc1 - globalBC);
653- int64_t dbc2 = std::abs (bc2 - globalBC);
654- return (dbc1 <= dbc2) ? index1 : index2;
645+ int32_t first = std::max (0 , localBC - maxDiff);
646+ int32_t last = std::min (nBCsPerOrbit - 1 , localBC + maxDiff);
647+ for (int32_t b = first; b <= last; b++) {
648+ if (bcPatternB[b]) {
649+ return b;
650+ }
651+ }
652+ return -1 ;
655653 }
656654
657655 // helper function to find median time in the vector of TOF or TRD-track times
@@ -765,14 +763,24 @@ class EventSelectionModule
765763 // colliding bc pattern
766764 int64_t ts = timestamps[0 ];
767765
768- // getForTimeStamp replaced with getSpecific to set metadata to zero
769- // avoids crash related to specific run number
770- auto grplhcif = ccdb->template getSpecific <o2::parameters::GRPLHCIFData>(" GLO/Config/GRPLHCIF" , ts);
771- bcPatternB = grplhcif->getBunchFilling ().getBCPattern ();
772- bcsPattern = grplhcif->getBunchFilling ().getFilledBCs ();
766+ // GRPLHCIF is taken from AggregatedRunInfo (fetched at mid-run, without metadata)
767+ bcPatternB = runInfo.grpLHC ->getBunchFilling ().getBCPattern ();
773768 if (runLightIons >= 0 ) {
774- for (uint32_t i = 0 ; i < bcsPattern.size (); i++)
775- LOGP (debug, " bcsPattern: i={} bc={}" , i, bcsPattern.at (i));
769+ for (int32_t b = 0 ; b < nBCsPerOrbit; b++) {
770+ if (bcPatternB[b]) {
771+ LOGP (debug, " bcPatternB: colliding bc={}" , b);
772+ }
773+ }
774+ }
775+
776+ // TEMPORARY cross-check: compare with GRPLHCIF fetched at the timestamp of the first BC (previous approach).
777+ // Must stay after the copy above: this fetch may replace the cached object runInfo.grpLHC points to.
778+ // getSpecific (instead of getForTimeStamp) sets metadata to zero, avoids crash related to specific run number
779+ auto grplhcifTs = ccdb->template getSpecific <o2::parameters::GRPLHCIFData>(" GLO/Config/GRPLHCIF" , ts);
780+ if (grplhcifTs->getBunchFilling ().getBCPattern () != bcPatternB) {
781+ LOGP (error, " EventSelectionModule: bcPatternB mismatch for run {}: runInfo.grpLHC (mid-run) vs GRPLHCIF at ts={}" , run, ts);
782+ } else {
783+ LOGP (info, " EventSelectionModule: bcPatternB cross-check OK for run {} (ts={})" , run, ts);
776784 }
777785
778786 // extract ITS ROF parameters
@@ -974,7 +982,7 @@ class EventSelectionModule
974982 float sumTime = 0 , sumW = 0 , sumHighPtTime = 0 , sumHighPtW = 0 ;
975983 for (const auto & track : colPvTracks) {
976984 float trackTime = track.trackTime ();
977- if (track.itsNCls () >= 5 ) // o2-linter: disable=magic-number (indeed counting layers 5 6 7 )
985+ if (track.itsNCls () >= 5 ) // o2-linter: disable=magic-number (number of ITS clusters >=5 )
978986 vTracksITS567perColl[colIndex]++;
979987 if (track.hasTRD ())
980988 vIsVertexTRDmatched[colIndex] = 1 ;
@@ -1019,15 +1027,10 @@ class EventSelectionModule
10191027 // alternative collision-BC matching (currently: test mode, the aim is to improve pileup rejection)
10201028 if (runLightIons >= 0 ) {
10211029 foundGlobalBC = globalBC;
1022- // find closest nominal bc in pattern
1023- for (uint32_t i = 0 ; i < bcsPattern.size (); i++) {
1024- int32_t localBC = globalBC % nBCsPerOrbit;
1025- int32_t bcFromPattern = bcsPattern.at (i);
1026- int64_t bcDiff = bcFromPattern - localBC;
1027- if (std::abs (bcDiff) <= 20 ) { // o2-linter: disable=magic-number (max BC difference to match pattern)
1028- foundGlobalBC = (globalBC / nBCsPerOrbit) * nBCsPerOrbit + bcFromPattern;
1029- break ; // the bc in pattern is found
1030- }
1030+ // find nominal bc in pattern
1031+ int32_t bcFromPattern = findBCinPattern (globalBC % nBCsPerOrbit);
1032+ if (bcFromPattern >= 0 ) { // the bc in pattern is found
1033+ foundGlobalBC = (globalBC / nBCsPerOrbit) * nBCsPerOrbit + bcFromPattern;
10311034 }
10321035
10331036 // matched with TOF --> precise time, match to TVX, but keep the nominal foundGlobalBC from pattern
@@ -1053,18 +1056,14 @@ class EventSelectionModule
10531056 // end of if TOF-matched vertex
10541057 } else {
10551058 // for non-TOF and low-mult vertices, consider nearby nominal bcs
1056- int64_t meanBC = globalBC + TMath::Nint (sumHighPtTime / sumHighPtW / bcNS);
1059+ int64_t meanBC = globalBC + (sumHighPtW > 0 ? TMath::Nint (sumHighPtTime / sumHighPtW / bcNS) : 0 );
10571060 int64_t bestGlobalBC = findBestGlobalBC (meanBC, evselOpts.confSigmaBCforHighPtTracks , vNcontributors[colIndex], col.posZ (), mapGlobalBcVtxZ);
10581061 if (bestGlobalBC > 0 ) {
10591062 foundGlobalBC = bestGlobalBC;
1060- // find closest nominal bc in pattern
1061- for (uint32_t j = 0 ; j < bcsPattern.size (); j++) {
1062- int32_t bcFromPatternBest = bcsPattern.at (j);
1063- int64_t bcDiff = bcFromPatternBest - (bestGlobalBC % nBCsPerOrbit);
1064- if (std::abs (bcDiff) <= 20 ) { // o2-linter: disable=magic-number (max BC difference to match pattern)
1065- foundGlobalBC = (bestGlobalBC / nBCsPerOrbit) * nBCsPerOrbit + bcFromPatternBest;
1066- break ; // the bc in pattern is found
1067- }
1063+ // find nominal bc in pattern
1064+ int32_t bcFromPatternBest = findBCinPattern (bestGlobalBC % nBCsPerOrbit);
1065+ if (bcFromPatternBest >= 0 ) { // the bc in pattern is found
1066+ foundGlobalBC = (bestGlobalBC / nBCsPerOrbit) * nBCsPerOrbit + bcFromPatternBest;
10681067 }
10691068 foundBCindex = mapGlobalBcWithTVX[bestGlobalBC];
10701069 } else { // failed to find a proper TVX with small vZ difference
@@ -1098,7 +1097,7 @@ class EventSelectionModule
10981097 } else if (nPvTracksHighPtTPCnoTOFnoTRD > 0 ) {
10991098 // for collisions with high-pt ITSTPC-nonTOF-nonTRD tracks
11001099 // search in 3*confSigmaBCforHighPtTracks range (3*4 bcs by default)
1101- int64_t meanBC = globalBC + TMath::Nint (sumHighPtTime / sumHighPtW / bcNS);
1100+ int64_t meanBC = globalBC + (sumHighPtW > 0 ? TMath::Nint (sumHighPtTime / sumHighPtW / bcNS) : 0 );
11021101 int64_t bestGlobalBC = findBestGlobalBC (meanBC, evselOpts.confSigmaBCforHighPtTracks , vNcontributors[colIndex], col.posZ (), mapGlobalBcVtxZ);
11031102 if (bestGlobalBC > 0 ) {
11041103 foundGlobalBC = bestGlobalBC;
@@ -1155,6 +1154,7 @@ class EventSelectionModule
11551154 const float timeWinOccupancyCalcMinNS = evselOpts.confTimeIntervalForOccupancyCalculationMin * 1e3 ; // ns
11561155 const float timeWinOccupancyCalcMaxNS = evselOpts.confTimeIntervalForOccupancyCalculationMax * 1e3 ; // ns
11571156
1157+ // loop over collisions to calculate occupancy-related quantities
11581158 for (const auto & col : cols) {
11591159 int32_t colIndex = col.globalIndex ();
11601160 int64_t foundGlobalBC = vFoundGlobalBC[colIndex];
@@ -1163,6 +1163,11 @@ class EventSelectionModule
11631163
11641164 int32_t foundBC = vFoundBCindex[colIndex];
11651165 auto bcselEntry = bcselbuffer[foundBC];
1166+ if (bcselEntry.foundFT0Id > -1 ) {
1167+ // required: explicit ft0s table
1168+ auto foundFT0 = ft0s.rawIteratorAt (bcselEntry.foundFT0Id );
1169+ vAmpFT0CperColl[colIndex] = foundFT0.sumAmpC ();
1170+ }
11661171 // check if we are close to ITS ROF borders => N ITS tracks is not reliable, and FT0C ampl can be used for occupancy estimation
11671172 // denominator for vAmpFT0CperColl is the approximate conversion factor b/n FT0C ampl and number of PV tracks after cuts
11681173 vProxyForCollNtracks[colIndex] = BITCHECK64 (bcselEntry.selection , aod::evsel::kNoITSROFrameBorder ) ? vTracksITS567perColl[colIndex] : vAmpFT0CperColl[colIndex] / 10 .;
@@ -1183,12 +1188,6 @@ class EventSelectionModule
11831188 for (const auto & col : cols) {
11841189 int32_t colIndex = col.globalIndex ();
11851190 int64_t foundGlobalBC = vFoundGlobalBC[colIndex];
1186- auto bcselEntr = bcselbuffer[vFoundBCindex[colIndex]];
1187- if (bcselEntr.foundFT0Id > -1 ) {
1188- // required: explicit ft0s table
1189- auto foundFT0 = ft0s.rawIteratorAt (bcselEntr.foundFT0Id );
1190- vAmpFT0CperColl[colIndex] = foundFT0.sumAmpC ();
1191- }
11921191
11931192 int64_t tfId = (foundGlobalBC - bcSOR) / nBCsPerTF;
11941193 int64_t rofId = (foundGlobalBC + nBCsPerOrbit - rofOffset) / rofLength;
0 commit comments