From f43f26cc36ff20f5f9f4f4aa509c3fd87aa2e04c Mon Sep 17 00:00:00 2001 From: Fabrizio Grosa Date: Sat, 21 Feb 2026 14:48:47 +0100 Subject: [PATCH 1/3] Fix bc FDD shift for 2023 and use CTP info to define if bc has signal or not --- PWGMM/Lumi/Tasks/lumiStabilityPP.cxx | 138 ++++++++------------------- 1 file changed, 42 insertions(+), 96 deletions(-) diff --git a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx index 90d01ed327d..28192db628b 100644 --- a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx +++ b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx @@ -61,13 +61,6 @@ enum BCCategories { BCA = 0, // A side BCs (bunch-crossings that had beam o BCNSLFT0 = 9, // non-super-leading BCs for FT0 of type B (bunch-crossings that had beam from both sides but are not SL for FT0 activity for a configurable number of preceding BCs) NBCCategories }; } // namespace lumi -namespace aod -{ -// Columns to store the information about the presence of FT0 and FDD signals associated to a given BC -DECLARE_SOA_TABLE(BcDetectorInfo, "AOD", "BCDETECTORINFO", //! - indices::FT0Id, - indices::FDDId); -} // namespace aod } // namespace o2 using namespace o2; @@ -75,42 +68,15 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::lumi; -using BCsWithTimeStamps = soa::Join; - -struct BuildBcFlagTable { - - Produces bcFlags; - - void init(InitContext&) {} - - void process(aod::BC const& bc, - aod::FT0s const& ft0s, - aod::FDDs const& fdds) - { - int64_t idxFT0{-1}, idxFDD{-1}; - for (const auto& ft0 : ft0s) { - if (ft0.bcId() == bc.globalIndex()) { - idxFT0 = ft0.globalIndex(); - break; - } - } - for (const auto& fdd : fdds) { - if (fdd.bcId() == bc.globalIndex()) { - idxFDD = fdd.globalIndex(); - break; - } - } - bcFlags(idxFT0, idxFDD); - } -}; +using BCsWithTimeStamps = soa::Join; struct LumiStabilityPP { static constexpr int defaulFlags[1][NBCCategories] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}; Configurable> doTypeBC{"doTypeBC", {defaulFlags[0], NBCCategories, {"BCA", "BCB", "BCC", "BCE", "BCL", "BCSLFDD", "BCSLFT0", "BCNL", "BCNSLFDD", "BCNSLFT0"}}, "Create and fill histograms for different BC types"}; - Configurable numEmptyBCsBeforeLeadingBC{"numEmptyBCsBeforeLeadingBC", 5, "Number of empty BCs before a leading BC"}; - Configurable bcShiftFDDForData2023{"bcShiftFDDForData2023", -15, "Number of bc to shift for FDD to be applied for 2023 data only"}; + Configurable numEmptyBCsBeforeLeadingBC{"numEmptyBCsBeforeLeadingBC", 5, "Number of empty (SL) or non-B (L) BCs before a (super)leading BC"}; + Configurable bcShiftFDDForData2023{"bcShiftFDDForData2023", 7, "Number of bc to shift for FDD to be applied for 2023 data only"}; std::bitset beamPatternA, beamPatternC; std::bitset bcPatternA, bcPatternC, bcPatternB, bcPatternE, bcPatternL; @@ -132,8 +98,6 @@ struct LumiStabilityPP { std::map> histNBcsVsTime; std::map> histNBcsVsBcId; std::map> histTfPerMin; - std::map> histBcHasFT0; - std::map> histBcHasFDD; std::map> histFillingScheme; std::map> histFillTime; std::map> histInteractionRate; @@ -177,17 +141,6 @@ struct LumiStabilityPP { histFillTime[runNumber] = registry.add(Form("%d/FillTime", runNumber), "Fill time;Fill time;", HistType::kTH1D, {{1, 0, 1}}); histInteractionRate[runNumber] = registry.add(Form("%d/InteractionRate", runNumber), "Interaction rate (kHz);Interaction rate (kHz);", HistType::kTH1D, {{3000, 0., 3000.}}); - histBcHasFT0[runNumber] = registry.add(Form("%d/FITQA/BCHasFT0", runNumber), "Does the BC have FT0?;BC has FT0;TVX triggered according to CTP;#bf{#it{N}_{BC}}", HistType::kTH2D, {{2, -0.5, 1.5}, {2, -0.5, 1.5}}); - histBcHasFT0[runNumber]->GetYaxis()->SetBinLabel(1, "No CTP trigger"); - histBcHasFT0[runNumber]->GetYaxis()->SetBinLabel(2, "CTP triggered"); - histBcHasFT0[runNumber]->GetXaxis()->SetBinLabel(1, "No found FT0"); - histBcHasFT0[runNumber]->GetXaxis()->SetBinLabel(2, "Found FT0"); - histBcHasFDD[runNumber] = registry.add(Form("%d/FITQA/BCHasFDD", runNumber), "Does the BC have FDD?;BC has FDD;FDD triggered according to CTP;#bf{#it{N}_{BC}}", HistType::kTH2D, {{2, -0.5, 1.5}, {2, -0.5, 1.5}}); - histBcHasFDD[runNumber]->GetYaxis()->SetBinLabel(1, "No CTP trigger"); - histBcHasFDD[runNumber]->GetYaxis()->SetBinLabel(2, "CTP triggered"); - histBcHasFDD[runNumber]->GetXaxis()->SetBinLabel(1, "No found FDD"); - histBcHasFDD[runNumber]->GetXaxis()->SetBinLabel(2, "Found FDD"); - for (int iTrigger{0}; iTrigger < NTriggerAliases; ++iTrigger) { for (int iBCCategory{0}; iBCCategory < NBCCategories; ++iBCCategory) { if (doTypeBC->get(0u, iBCCategory)) { @@ -242,7 +195,7 @@ struct LumiStabilityPP { bcPatternB = beamPatternA & beamPatternC; bcPatternE = ~beamPatternA & ~beamPatternC; - // Create bcPatternL: leading BCs of type B that follow at least "numEmptyBCsBeforeLeadingBC" empty BCs + // Create bcPatternL: leading BCs of type B that follow at least "numEmptyBCsBeforeLeadingBC" non-B BCs bcPatternL.reset(); // Initialize all bits to false LOG(info) << "Starting to create bcPatternL from bcPatternB"; LOG(info) << "Total number of BCs to check: " << o2::constants::lhc::LHCMaxBunches; @@ -250,16 +203,16 @@ struct LumiStabilityPP { int totalLeadingBCs = 0; for (int iBC = 0; iBC < o2::constants::lhc::LHCMaxBunches; iBC++) { if (bcPatternB[iBC]) { // Check if current BC is of type B - int emptyBCsBefore = 0; // Count how many consecutive BCs before this one are NOT type B + int nonBBCsBefore = 0; // Count how many consecutive BCs before this one are NOT type B for (int j = 1; j <= numEmptyBCsBeforeLeadingBC; j++) { int prevBC = (iBC - j + o2::constants::lhc::LHCMaxBunches) % o2::constants::lhc::LHCMaxBunches; // Protection for BCs at small indices to check the end of the orbit if (!bcPatternB[prevBC]) { - emptyBCsBefore++; + nonBBCsBefore++; } else { break; // Stop counting if we hit a type B BC } } - if (emptyBCsBefore >= numEmptyBCsBeforeLeadingBC) { // If we found at least numEmptyBCsBeforeLeadingBC empty BCs before this one, mark it as leading + if (nonBBCsBefore >= numEmptyBCsBeforeLeadingBC) { // If we found at least numEmptyBCsBeforeLeadingBC empty BCs before this one, mark it as leading bcPatternL[iBC] = true; totalLeadingBCs++; } @@ -319,21 +272,16 @@ struct LumiStabilityPP { } setLHCIFData(bc); - BCsWithTimeStamps::iterator bcFDD; - auto idxBc = bc.globalIndex(); + int bcShiftFDD{0}; if (isData23) { - if ((bcShiftFDDForData2023 < 0 && idxBc < -bcShiftFDDForData2023) || (bcShiftFDDForData2023 > 0 && idxBc > bcs.size() - bcShiftFDDForData2023)) { // we need to skip the first/last bcs because of the FDD-FT0 shift - continue; - } - bcFDD = bcs.rawIteratorAt(idxBc + bcShiftFDDForData2023); + bcShiftFDD = bcShiftFDDForData2023; } else { - bcFDD = bc; + bcShiftFDD = 0; } - float timeSinceSOF = getTimeSinceSOF(bc); - bool isTriggerTVX = (bc.has_ft0() ? TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitVertex) : false); - if (isTriggerTVX) { + std::bitset<64> ctpInputMask(bc.inputMask()); + if (ctpInputMask.test(2)) { histNBcsVsTime[runNumber]->Fill(timeSinceSOF); int runVdM23Start{542757}; int runVdM23Stop{542768}; @@ -344,30 +292,34 @@ struct LumiStabilityPP { } int64_t globalBC = bc.globalBC(); + int64_t globalBCFDD = bc.globalBC() + bcShiftFDD; int localBC = globalBC % nBCsPerOrbit; + int localBCFDD = globalBCFDD % nBCsPerOrbit; bool isSuperLeadingBcFDD{true}, isSuperLeadingBcFT0{true}; - if (globalBC - globalBCIdOfLastBCWithActivityFDD < numEmptyBCsBeforeLeadingBC) { + if (globalBCFDD - globalBCIdOfLastBCWithActivityFDD < numEmptyBCsBeforeLeadingBC) { isSuperLeadingBcFDD = false; // not a super-leading BC for FDD } if (globalBC - globalBCIdOfLastBCWithActivityFT0 < numEmptyBCsBeforeLeadingBC) { isSuperLeadingBcFT0 = false; // not a super-leading BC for FT0 } - if (bcFDD.has_fdd()) { + if (ctpInputMask.test(13) || ctpInputMask.test(15) || ctpInputMask.test(16) || ctpInputMask.test(17)|| ctpInputMask.test(18)) { // 5 FDD triggers globalBCIdOfLastBCWithActivityFDD = globalBC; } - if (bc.has_ft0()) { - globalBCIdOfLastBCWithActivityFT0 = globalBC; + if (ctpInputMask.test(1) || ctpInputMask.test(2) || ctpInputMask.test(3) || ctpInputMask.test(4) || ctpInputMask.test(5)) { // 5 FT0 triggers + globalBCIdOfLastBCWithActivityFT0 = globalBCFDD; } if (!bcPatternB[localBC]) { - isSuperLeadingBcFDD = false; // not a super-leading BC isSuperLeadingBcFT0 = false; // not a super-leading BC } + if (!bcPatternB[localBCFDD]) { + isSuperLeadingBcFDD = false; // not a super-leading BC + } int64_t globalBCStart = (globalBCLastInspectedBC >= 0 && globalBCLastInspectedBC < globalBC) ? globalBCLastInspectedBC + 1 : globalBC; - int64_t maxBcDiff = (rate > 0) ? 10 * static_cast(nBunchesFillingScheme * constants::lhc::LHCRevFreq / rate / 1.e3) : 500; + int64_t maxBcDiff = (rate > 0) ? 10 * static_cast(nBunchesFillingScheme * constants::lhc::LHCRevFreq / rate / 1.e3) : 1500; if (globalBC - globalBCStart > maxBcDiff) { // we changed fill, we should not count all BCs between the current and the previous one globalBCStart = globalBC; } @@ -410,12 +362,6 @@ struct LumiStabilityPP { histTfPerMin[runNumber]->Fill(timeSinceSOF); } - std::bitset<64> ctpInputMask(bc.inputMask()); - std::bitset<64> ctpInputMaskFDD(bcFDD.inputMask()); - - histBcHasFT0[runNumber]->Fill(bc.has_ft0(), ctpInputMask.test(2)); - histBcHasFDD[runNumber]->Fill(bcFDD.has_fdd(), ctpInputMaskFDD.test(15)); - for (int iTrigger{0}; iTrigger < NTriggerAliases; ++iTrigger) { for (int iBCCategory{0}; iBCCategory < NBCCategories; ++iBCCategory) { if (doTypeBC->get(0u, iBCCategory)) { @@ -485,27 +431,27 @@ struct LumiStabilityPP { if (iBCCategory == BCNSLFT0 && !isSuperLeadingBcFT0 && bcPatternB[localBC]) fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); } - if (iTrigger == FDD && ctpInputMaskFDD.test(15)) { - if (iBCCategory == BCA && bcPatternA[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); - if (iBCCategory == BCB && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); - if (iBCCategory == BCC && bcPatternC[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); - if (iBCCategory == BCE && bcPatternE[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); - if (iBCCategory == BCL && bcPatternL[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + if (iTrigger == FDD && ctpInputMask.test(15)) { + if (iBCCategory == BCA && bcPatternA[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); + if (iBCCategory == BCB && bcPatternB[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); + if (iBCCategory == BCC && bcPatternC[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); + if (iBCCategory == BCE && bcPatternE[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); + if (iBCCategory == BCL && bcPatternL[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); if (iBCCategory == BCSLFDD && isSuperLeadingBcFDD) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); if (iBCCategory == BCSLFT0 && isSuperLeadingBcFT0) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); - if (iBCCategory == BCNL && !bcPatternL[localBC] && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); - if (iBCCategory == BCNSLFDD && !isSuperLeadingBcFDD && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); - if (iBCCategory == BCNSLFT0 && !isSuperLeadingBcFT0 && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); + if (iBCCategory == BCNL && !bcPatternL[localBCFDD] && bcPatternB[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); + if (iBCCategory == BCNSLFDD && !isSuperLeadingBcFDD && bcPatternB[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); + if (iBCCategory == BCNSLFT0 && !isSuperLeadingBcFT0 && bcPatternB[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); } } } @@ -540,5 +486,5 @@ struct LumiStabilityPP { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { metadataInfo.initMetadata(cfgc); - return WorkflowSpec{adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } From 285e57badf9dd6688df37c4387246507611a3096 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Sat, 21 Feb 2026 13:50:05 +0000 Subject: [PATCH 2/3] Please consider the following formatting changes --- PWGMM/Lumi/Tasks/lumiStabilityPP.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx index 28192db628b..4fea9b4e00b 100644 --- a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx +++ b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx @@ -203,7 +203,7 @@ struct LumiStabilityPP { int totalLeadingBCs = 0; for (int iBC = 0; iBC < o2::constants::lhc::LHCMaxBunches; iBC++) { if (bcPatternB[iBC]) { // Check if current BC is of type B - int nonBBCsBefore = 0; // Count how many consecutive BCs before this one are NOT type B + int nonBBCsBefore = 0; // Count how many consecutive BCs before this one are NOT type B for (int j = 1; j <= numEmptyBCsBeforeLeadingBC; j++) { int prevBC = (iBC - j + o2::constants::lhc::LHCMaxBunches) % o2::constants::lhc::LHCMaxBunches; // Protection for BCs at small indices to check the end of the orbit if (!bcPatternB[prevBC]) { @@ -304,7 +304,7 @@ struct LumiStabilityPP { isSuperLeadingBcFT0 = false; // not a super-leading BC for FT0 } - if (ctpInputMask.test(13) || ctpInputMask.test(15) || ctpInputMask.test(16) || ctpInputMask.test(17)|| ctpInputMask.test(18)) { // 5 FDD triggers + if (ctpInputMask.test(13) || ctpInputMask.test(15) || ctpInputMask.test(16) || ctpInputMask.test(17) || ctpInputMask.test(18)) { // 5 FDD triggers globalBCIdOfLastBCWithActivityFDD = globalBC; } if (ctpInputMask.test(1) || ctpInputMask.test(2) || ctpInputMask.test(3) || ctpInputMask.test(4) || ctpInputMask.test(5)) { // 5 FT0 triggers From fc705e248f5625dd5de8a2247fd2f3b4efde0250 Mon Sep 17 00:00:00 2001 From: Fabrizio Grosa Date: Sat, 21 Feb 2026 14:55:49 +0100 Subject: [PATCH 3/3] Change leading BC definition --- PWGMM/Lumi/Tasks/lumiStabilityPP.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx index 4fea9b4e00b..e0ca847029b 100644 --- a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx +++ b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx @@ -75,7 +75,7 @@ struct LumiStabilityPP { static constexpr int defaulFlags[1][NBCCategories] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}; Configurable> doTypeBC{"doTypeBC", {defaulFlags[0], NBCCategories, {"BCA", "BCB", "BCC", "BCE", "BCL", "BCSLFDD", "BCSLFT0", "BCNL", "BCNSLFDD", "BCNSLFT0"}}, "Create and fill histograms for different BC types"}; - Configurable numEmptyBCsBeforeLeadingBC{"numEmptyBCsBeforeLeadingBC", 5, "Number of empty (SL) or non-B (L) BCs before a (super)leading BC"}; + Configurable numEmptyBCsBeforeLeadingBC{"numEmptyBCsBeforeLeadingBC", 5, "Number of empty BCs before a (super)leading BC"}; Configurable bcShiftFDDForData2023{"bcShiftFDDForData2023", 7, "Number of bc to shift for FDD to be applied for 2023 data only"}; std::bitset beamPatternA, beamPatternC; @@ -203,16 +203,16 @@ struct LumiStabilityPP { int totalLeadingBCs = 0; for (int iBC = 0; iBC < o2::constants::lhc::LHCMaxBunches; iBC++) { if (bcPatternB[iBC]) { // Check if current BC is of type B - int nonBBCsBefore = 0; // Count how many consecutive BCs before this one are NOT type B + int emptyBCsBefore = 0; // Count how many consecutive BCs before this one are empty for (int j = 1; j <= numEmptyBCsBeforeLeadingBC; j++) { int prevBC = (iBC - j + o2::constants::lhc::LHCMaxBunches) % o2::constants::lhc::LHCMaxBunches; // Protection for BCs at small indices to check the end of the orbit - if (!bcPatternB[prevBC]) { - nonBBCsBefore++; + if (bcPatternE[prevBC]) { + emptyBCsBefore++; } else { - break; // Stop counting if we hit a type B BC + break; // Stop counting if we hit a non-empty BC } } - if (nonBBCsBefore >= numEmptyBCsBeforeLeadingBC) { // If we found at least numEmptyBCsBeforeLeadingBC empty BCs before this one, mark it as leading + if (emptyBCsBefore >= numEmptyBCsBeforeLeadingBC) { // If we found at least numEmptyBCsBeforeLeadingBC empty BCs before this one, mark it as leading bcPatternL[iBC] = true; totalLeadingBCs++; }