From abd09b6b59b78f1b5ca4dd96bdd6d861886fddf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Tiek=C3=B6tter?= Date: Mon, 26 Oct 2026 17:24:48 +0100 Subject: [PATCH 1/2] Implement possibility to select RCT Flags in tableReader_withAssoc and dqEfficiency_withAssoc. --- PWGDQ/Tasks/dqEfficiency_withAssoc.cxx | 53 +++++++++++++++++++++++++- PWGDQ/Tasks/tableReader_withAssoc.h | 53 +++++++++++++++++++++++++- 2 files changed, 104 insertions(+), 2 deletions(-) diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx index 176d7ce64b2..72920db7682 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx @@ -24,6 +24,7 @@ #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/TableHelper.h" #include @@ -309,6 +310,10 @@ struct AnalysisEventSelection { Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; + Configurable cfgUseRCT{"cfgUseRCT", false, "Apply RCT quality selection"}; + Configurable cfgRCTLabel{"cfgRCTLabel", "CBT", "RCT selection label"}; + Configurable cfgCheckZDC{"cfgCheckZDC", false, "Also check ZDC quality"}; + HistogramManager* fHistMan = nullptr; MixingHandler* fMixHandler = nullptr; @@ -322,6 +327,10 @@ struct AnalysisEventSelection { std::map fMetadataRCT, fHeader; int fCurrentRun = -1; + o2::aod::rctsel::RCTFlagsChecker rctChecker{"CBT"}; + std::map rctFlags; + int rctRun = -1; + void init(o2::framework::InitContext& context) { if (context.mOptions.get("processDummy")) { @@ -378,6 +387,48 @@ struct AnalysisEventSelection { fCCDB->setLocalObjectValidityChecking(); fCCDB->setCreatedNotAfter(fConfigNoLaterThan.value); fCCDBApi.init(fConfigCcdbUrl.value); + + if (cfgUseRCT.value) { + rctChecker.init(cfgRCTLabel.value, cfgCheckZDC.value); + + if (!rctChecker.any()) { + LOGF(fatal, "Empty RCT mask: check cfgRCTLabel"); + } + } + } + + void loadRCT(int run, uint64_t timestamp) + { + std::map metadata{{"run", std::to_string(run)}}; + + auto* flags = fCCDB->getSpecific>("RCT/Flags/RunFlags", timestamp, metadata); + if (flags == nullptr || flags->empty()) { + LOGF(fatal, "Missing or empty RCT flags for run " + std::to_string(run)); + } + + LOG(info) << "Requesting RCT/Flags/RunFlags" << " run=" << run << " timestamp=" << timestamp; + + rctFlags = *flags; + rctRun = run; + } + + bool passesRCT(int run, uint64_t timestamp) + { + if (!cfgUseRCT.value) { + return true; + } + + if (run != rctRun) { + loadRCT(run, timestamp); + } + + auto iterator = rctFlags.upper_bound(timestamp); + if (iterator == rctFlags.begin()) { + return false; + } + + const uint32_t flags = std::prev(iterator)->second; + return (static_cast(flags) & rctChecker.value()) == 0; } template @@ -406,7 +457,7 @@ struct AnalysisEventSelection { if (fConfigQA) { fHistMan->FillHistClass("Event_BeforeCuts", dqefficiency_helpers::varValues()); // automatically fill all the histograms in the class Event } - if (fEventCut->IsSelected(dqefficiency_helpers::varValues())) { + if (fEventCut->IsSelected(dqefficiency_helpers::varValues()) && passesRCT(event.runNumber(), event.timestamp())) { if (fConfigQA) { fHistMan->FillHistClass("Event_AfterCuts", dqefficiency_helpers::varValues()); } diff --git a/PWGDQ/Tasks/tableReader_withAssoc.h b/PWGDQ/Tasks/tableReader_withAssoc.h index 88bdbc0fd67..12cb03907d0 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.h +++ b/PWGDQ/Tasks/tableReader_withAssoc.h @@ -30,6 +30,7 @@ #include "PWGDQ/DataModel/ReducedInfoTables.h" #include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/CCDB/ctpRateFetcher.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/TableHelper.h" @@ -339,6 +340,10 @@ struct AnalysisEventSelection { o2::framework::Configurable fConfigFetchInteractionRate{"cfgFetchInteractionRate", false, "Fetch event-wise interaction rate from the CCDB"}; o2::framework::Configurable fConfigIRSource{"cfgIRSource", "ZNC hadronic", "Estimator of the interaction rate (Recommended: pp --> T0VTX, Pb-Pb --> ZNC hadronic)"}; + o2::framework::Configurable cfgUseRCT{"cfgUseRCT", false, "Apply RCT quality selection"}; + o2::framework::Configurable cfgRCTLabel{"cfgRCTLabel", "CBT", "RCT selection label"}; + o2::framework::Configurable cfgCheckZDC{"cfgCheckZDC", false, "Also check ZDC quality"}; + HistogramManager* fHistMan = nullptr; MixingHandler* fMixHandler = nullptr; AnalysisCompositeCut* fEventCut = nullptr; @@ -351,6 +356,10 @@ struct AnalysisEventSelection { std::map> fBCCollMap; // key: global BC, value: vector of reduced event global indices int fCurrentRun = -1; + o2::aod::rctsel::RCTFlagsChecker rctChecker{"CBT"}; + std::map rctFlags; + int rctRun = -1; + void init(o2::framework::InitContext& context) { @@ -424,6 +433,48 @@ struct AnalysisEventSelection { fCCDB->setLocalObjectValidityChecking(); fCCDB->setCreatedNotAfter(fConfigNoLaterThan.value); fCCDBApi.init(fConfigCcdbUrl.value); + + if (cfgUseRCT.value) { + rctChecker.init(cfgRCTLabel.value, cfgCheckZDC.value); + + if (!rctChecker.any()) { + LOGF(fatal, "Empty RCT mask: check cfgRCTLabel"); + } + } + } + + void loadRCT(int run, uint64_t timestamp) + { + std::map metadata{{"run", std::to_string(run)}}; + + auto* flags = fCCDB->getSpecific>("RCT/Flags/RunFlags", timestamp, metadata); + if (flags == nullptr || flags->empty()) { + LOGF(fatal, "Missing or empty RCT flags for run " + std::to_string(run)); + } + + LOG(info) << "Requesting RCT/Flags/RunFlags" << " run=" << run << " timestamp=" << timestamp; + + rctFlags = *flags; + rctRun = run; + } + + bool passesRCT(int run, uint64_t timestamp) + { + if (!cfgUseRCT.value) { + return true; + } + + if (run != rctRun) { + loadRCT(run, timestamp); + } + + auto iterator = rctFlags.upper_bound(timestamp); + if (iterator == rctFlags.begin()) { + return false; + } + + const uint32_t flags = std::prev(iterator)->second; + return (static_cast(flags) & rctChecker.value()) == 0; } template @@ -463,7 +514,7 @@ struct AnalysisEventSelection { } // Apply event cuts and fill histograms after selection - if (fEventCut->IsSelected(dqtablereader_helpers::varValues())) { + if (fEventCut->IsSelected(dqtablereader_helpers::varValues()) && passesRCT(event.runNumber(), event.timestamp())) { if (fConfigRunZorro) { if (event.tag_bit(56)) { // This is the bit used for the software trigger event selections [TO BE DONE: find a more clear way to use it] if (fConfigQA) { From 3fd8b0b4a1ef6397e527f677769fc509de984a17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Tiek=C3=B6tter?= Date: Tue, 27 Oct 2026 18:54:08 +0100 Subject: [PATCH 2/2] Add configurable for passName and check validity of input flag --- PWGDQ/Tasks/dqEfficiency_withAssoc.cxx | 31 +++++++++++++++++++------- PWGDQ/Tasks/tableReader_withAssoc.h | 26 ++++++++++++++++----- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx index 72920db7682..626252dc2f4 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx @@ -310,9 +310,11 @@ struct AnalysisEventSelection { Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; - Configurable cfgUseRCT{"cfgUseRCT", false, "Apply RCT quality selection"}; - Configurable cfgRCTLabel{"cfgRCTLabel", "CBT", "RCT selection label"}; - Configurable cfgCheckZDC{"cfgCheckZDC", false, "Also check ZDC quality"}; + o2::framework::Configurable cfgUseRCT{"cfgUseRCT", false, "Apply RCT quality selection"}; + o2::framework::Configurable cfgRCTPath{"cfgRCTPath", "RCT/Flags/RunFlags", "CCDB path to the RCT run flags"}; + o2::framework::Configurable cfgRCTLabel{"cfgRCTLabel", "CBT", "RCT selection label"}; + o2::framework::Configurable cfgCheckZDC{"cfgCheckZDC", false, "Also check ZDC quality"}; + o2::framework::Configurable cfgRCTPassName{"cfgRCTPassName", "", "Reconstruction pass; leave empty for run-only lookup"}; HistogramManager* fHistMan = nullptr; MixingHandler* fMixHandler = nullptr; @@ -389,10 +391,14 @@ struct AnalysisEventSelection { fCCDBApi.init(fConfigCcdbUrl.value); if (cfgUseRCT.value) { + if (cfgRCTLabel.value != "CBT" && cfgRCTLabel.value != "CBT_hadronPID" && cfgRCTLabel.value != "CBT_electronPID" && cfgRCTLabel.value != "CBT_calo" && cfgRCTLabel.value != "CBT_muon" && cfgRCTLabel.value != "CBT_muon_glo") { + LOGF(fatal, "RCT Label \"%s\" is unknown.", cfgRCTLabel.value.c_str()); + } + rctChecker.init(cfgRCTLabel.value, cfgCheckZDC.value); if (!rctChecker.any()) { - LOGF(fatal, "Empty RCT mask: check cfgRCTLabel"); + LOGF(fatal, "Empty RCT mask: check cfgRCTLabel."); } } } @@ -401,12 +407,21 @@ struct AnalysisEventSelection { { std::map metadata{{"run", std::to_string(run)}}; - auto* flags = fCCDB->getSpecific>("RCT/Flags/RunFlags", timestamp, metadata); - if (flags == nullptr || flags->empty()) { - LOGF(fatal, "Missing or empty RCT flags for run " + std::to_string(run)); + LOG(info) << "Requesting " << cfgRCTPath.value << " run=" << run << " timestamp=" << timestamp; + + if (!cfgRCTPassName.value.empty()) { + metadata["passName"] = cfgRCTPassName.value; } - LOG(info) << "Requesting RCT/Flags/RunFlags" << " run=" << run << " timestamp=" << timestamp; + auto* flags = fCCDB->getSpecific>(cfgRCTPath.value, timestamp, metadata); + if (flags == nullptr && !cfgRCTPassName.value.empty()) { + metadata.erase("passName"); + flags = fCCDB->getSpecific>(cfgRCTPath.value, timestamp, metadata); + } + + if (flags == nullptr || flags->empty()) { + LOGF(fatal, "Missing or empty RCT flags for run %d.", run); + } rctFlags = *flags; rctRun = run; diff --git a/PWGDQ/Tasks/tableReader_withAssoc.h b/PWGDQ/Tasks/tableReader_withAssoc.h index 12cb03907d0..af99435212a 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.h +++ b/PWGDQ/Tasks/tableReader_withAssoc.h @@ -341,8 +341,10 @@ struct AnalysisEventSelection { o2::framework::Configurable fConfigIRSource{"cfgIRSource", "ZNC hadronic", "Estimator of the interaction rate (Recommended: pp --> T0VTX, Pb-Pb --> ZNC hadronic)"}; o2::framework::Configurable cfgUseRCT{"cfgUseRCT", false, "Apply RCT quality selection"}; + o2::framework::Configurable cfgRCTPath{"cfgRCTPath", "RCT/Flags/RunFlags", "CCDB path to the RCT run flags"}; o2::framework::Configurable cfgRCTLabel{"cfgRCTLabel", "CBT", "RCT selection label"}; o2::framework::Configurable cfgCheckZDC{"cfgCheckZDC", false, "Also check ZDC quality"}; + o2::framework::Configurable cfgRCTPassName{"cfgRCTPassName", "", "Reconstruction pass; leave empty for run-only lookup"}; HistogramManager* fHistMan = nullptr; MixingHandler* fMixHandler = nullptr; @@ -362,7 +364,6 @@ struct AnalysisEventSelection { void init(o2::framework::InitContext& context) { - bool isAnyProcessEnabled = context.mOptions.get("processSkimmed") || context.mOptions.get("processSkimmedBasic") || context.mOptions.get("processSkimmedWithZdc") || context.mOptions.get("processSkimmedWithMultExtra") || context.mOptions.get("processSkimmedWithMultExtraNoQvector") || context.mOptions.get("processSkimmedWithMultExtraZdc") || context.mOptions.get("processSkimmedWithMultExtraZdcFit") || context.mOptions.get("processSkimmedWithQvectorCentr") || context.mOptions.get("processSkimmedWithQvectorCentrMerge"); bool isDummyEnabled = context.mOptions.get("processDummy"); @@ -435,10 +436,14 @@ struct AnalysisEventSelection { fCCDBApi.init(fConfigCcdbUrl.value); if (cfgUseRCT.value) { + if (cfgRCTLabel.value != "CBT" && cfgRCTLabel.value != "CBT_hadronPID" && cfgRCTLabel.value != "CBT_electronPID" && cfgRCTLabel.value != "CBT_calo" && cfgRCTLabel.value != "CBT_muon" && cfgRCTLabel.value != "CBT_muon_glo") { + LOGF(fatal, "RCT Label \"%s\" is unknown.", cfgRCTLabel.value.c_str()); + } + rctChecker.init(cfgRCTLabel.value, cfgCheckZDC.value); if (!rctChecker.any()) { - LOGF(fatal, "Empty RCT mask: check cfgRCTLabel"); + LOGF(fatal, "Empty RCT mask: check cfgRCTLabel."); } } } @@ -447,12 +452,21 @@ struct AnalysisEventSelection { { std::map metadata{{"run", std::to_string(run)}}; - auto* flags = fCCDB->getSpecific>("RCT/Flags/RunFlags", timestamp, metadata); - if (flags == nullptr || flags->empty()) { - LOGF(fatal, "Missing or empty RCT flags for run " + std::to_string(run)); + LOG(info) << "Requesting " << cfgRCTPath.value << " run=" << run << " timestamp=" << timestamp; + + if (!cfgRCTPassName.value.empty()) { + metadata["passName"] = cfgRCTPassName.value; } - LOG(info) << "Requesting RCT/Flags/RunFlags" << " run=" << run << " timestamp=" << timestamp; + auto* flags = fCCDB->getSpecific>(cfgRCTPath.value, timestamp, metadata); + if (flags == nullptr && !cfgRCTPassName.value.empty()) { + metadata.erase("passName"); + flags = fCCDB->getSpecific>(cfgRCTPath.value, timestamp, metadata); + } + + if (flags == nullptr || flags->empty()) { + LOGF(fatal, "Missing or empty RCT flags for run %d.", run); + } rctFlags = *flags; rctRun = run;