diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx index 176d7ce64b2..626252dc2f4 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,12 @@ 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"}; + 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; @@ -322,6 +329,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 +389,61 @@ struct AnalysisEventSelection { fCCDB->setLocalObjectValidityChecking(); fCCDB->setCreatedNotAfter(fConfigNoLaterThan.value); 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."); + } + } + } + + void loadRCT(int run, uint64_t timestamp) + { + std::map metadata{{"run", std::to_string(run)}}; + + LOG(info) << "Requesting " << cfgRCTPath.value << " run=" << run << " timestamp=" << timestamp; + + if (!cfgRCTPassName.value.empty()) { + metadata["passName"] = cfgRCTPassName.value; + } + + 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; + } + + 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 +472,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..af99435212a 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,12 @@ 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 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; AnalysisCompositeCut* fEventCut = nullptr; @@ -351,9 +358,12 @@ 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) { - 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"); @@ -424,6 +434,61 @@ struct AnalysisEventSelection { fCCDB->setLocalObjectValidityChecking(); fCCDB->setCreatedNotAfter(fConfigNoLaterThan.value); 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."); + } + } + } + + void loadRCT(int run, uint64_t timestamp) + { + std::map metadata{{"run", std::to_string(run)}}; + + LOG(info) << "Requesting " << cfgRCTPath.value << " run=" << run << " timestamp=" << timestamp; + + if (!cfgRCTPassName.value.empty()) { + metadata["passName"] = cfgRCTPassName.value; + } + + 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; + } + + 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 +528,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) {