From 29dae054f7a393e92dde3680a0ca2426b0e2f4c6 Mon Sep 17 00:00:00 2001 From: Emil Gorm Nielsen Date: Tue, 20 Oct 2026 20:05:11 +0200 Subject: [PATCH 1/3] Add custom event selection to energyFlowGfw.cxx --- .../GenericFramework/Tasks/energyFlowGfw.cxx | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/PWGCF/GenericFramework/Tasks/energyFlowGfw.cxx b/PWGCF/GenericFramework/Tasks/energyFlowGfw.cxx index e1d2ea659cc..3c9768fa42d 100644 --- a/PWGCF/GenericFramework/Tasks/energyFlowGfw.cxx +++ b/PWGCF/GenericFramework/Tasks/energyFlowGfw.cxx @@ -18,6 +18,7 @@ #include "PWGCF/GenericFramework/Core/GFWConfig.h" #include "PWGCF/GenericFramework/Core/GFWWeights.h" +#include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" @@ -136,6 +137,7 @@ struct EnergyFlowGfw { Configurable cfgMaxCentrality{"cfgMaxCentrality", 100.f, "Maximum accepted centrality percentile"}; Configurable cfgFillEfficiency{"fillEfficiency", false, "Fill MC tracking efficiency; ignored by data processes"}; Configurable cfgFillAcceptance{"fillAcceptance", false, "Fill GFW acceptance weights instead of running the reconstructed analysis"}; + Configurable cfgUseRun2EventSelectionWithoutZdc{"cfgUseRun2EventSelectionWithoutZdc", false, "For Run 2 data, require kINT7 and every CCDB-enabled barrel sel7 criterion except the ZDC beam-beam criteria; retain the ZDC beam-gas vetoes"}; Configurable cfgSpectatorEnergyPerNucleon{"cfgSpectatorEnergyPerNucleon", 1.f, "ZDC energy corresponding to one spectator nucleon"}; Configurable cfgMaxTotalSpectators{"cfgMaxTotalSpectators", 500.f, "Maximum accepted spectator count from ZNA+ZNC+ZPA+ZPC"}; @@ -601,6 +603,41 @@ struct EnergyFlowGfw { return true; } + static bool isZdcBeamBeamSelectionFlag(int flag) + { + return flag == aod::evsel::kIsBBZNA || flag == aod::evsel::kIsBBZNC || flag == aod::evsel::kIsBBZAC; + } + + template + bool run2EventSelected(TCollision const& collision) + { + if (!collision.alias_bit(kINT7)) { + return false; + } + if (!cfgUseRun2EventSelectionWithoutZdc) { + return collision.sel7(); + } + if (!collision.has_foundBC()) { + return false; + } + + const auto& bc = collision.template foundBC_as(); + auto* selectionParameters = ccdb->getForTimeStamp("EventSelection/EventSelectionParams", bc.timestamp()); + if (!selectionParameters) { + LOGF(fatal, "Could not load the Run 2 event-selection parameters"); + } + const bool* enabledSelections = selectionParameters->getSelection(0); + for (int flag = 0; flag < aod::evsel::kNsel; ++flag) { + if (isZdcBeamBeamSelectionFlag(flag)) { + continue; + } + if (enabledSelections[flag] && !collision.selection_bit(flag)) { + return false; + } + } + return true; + } + void loadEfficiency(uint64_t timestamp) { if (efficiencyPath.value.empty()) { @@ -868,7 +905,7 @@ struct EnergyFlowGfw { void processRun2(CollisionsRun2::iterator const& collision, Tracks const& tracks, BCsRun2 const&, aod::Zdcs const&) { float spectators = -1.f; - if (!eventSelected(collision, collision.alias_bit(kINT7) && collision.sel7(), static_cast(tracks.size()), collision.centRun2V0M(), spectators)) { + if (!eventSelected(collision, run2EventSelected(collision), static_cast(tracks.size()), collision.centRun2V0M(), spectators)) { return; } if (cfgFillAcceptance) { From ae4253f6b8a19639ff0332bf7d41d1ec5a793b8b Mon Sep 17 00:00:00 2001 From: Emil Gorm Nielsen Date: Tue, 20 Oct 2026 20:17:48 +0200 Subject: [PATCH 2/3] modify efficiency loading --- .../GenericFramework/Tasks/energyFlowGfw.cxx | 82 ++++++++++--------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/PWGCF/GenericFramework/Tasks/energyFlowGfw.cxx b/PWGCF/GenericFramework/Tasks/energyFlowGfw.cxx index 3c9768fa42d..db7d4c1cdb5 100644 --- a/PWGCF/GenericFramework/Tasks/energyFlowGfw.cxx +++ b/PWGCF/GenericFramework/Tasks/energyFlowGfw.cxx @@ -40,7 +40,6 @@ #include #include -#include #include #include #include @@ -147,8 +146,10 @@ struct EnergyFlowGfw { Configurable cfgZdcResponseZPC{"cfgZdcResponseZPC", 1.f, "ZPC efficiency/acceptance response factor alpha; corrected energy is E_ZPC/alpha_ZPC"}; Configurable cfgZdcMaxAbsTimeForQa{"cfgZdcMaxAbsTimeForQa", 100.f, "Maximum absolute ZDC time considered available in QA; excludes missing-time sentinels"}; - Configurable efficiencyPath{"efficiencyPath", "", "CCDB path or local ROOT file containing a 4D efficiency-correction THn"}; - Configurable efficiencyFromLocalFile{"efficiencyFromLocalFile", false, "Load efficiencyPath from a local ROOT file"}; + struct : ConfigurableGroup { + Configurable cfgEfficiencyPath{"cfgEfficiencyPath", "", "CCDB path to efficiency object"}; + Configurable cfgUsePIDEfficiencies{"cfgUsePIDEfficiencies", false, "Use separate charged, pion, kaon, and proton efficiencies"}; + } cfgEfficiency; Configurable acceptancePath{"acceptancePath", "", "CCDB path to GFW acceptance weights"}; Configurable acceptanceRunByRun{"acceptanceRunByRun", false, "Load acceptance weights from the RunByRun subdirectory"}; @@ -199,8 +200,9 @@ struct EnergyFlowGfw { std::vector zeroHarmonicConfigs; int gfwMask = 0; - std::unique_ptr localEfficiency; - THn* efficiency = nullptr; + TH1* efficiency = nullptr; + std::vector pidEfficiencies; + bool efficiencyLoaded = false; GFWWeights* acceptance = nullptr; int acceptanceRunNumber = -1; @@ -640,37 +642,33 @@ struct EnergyFlowGfw { void loadEfficiency(uint64_t timestamp) { - if (efficiencyPath.value.empty()) { - efficiency = nullptr; + if (efficiencyLoaded) { return; } - if (efficiencyFromLocalFile) { - if (localEfficiency) { - efficiency = localEfficiency.get(); - return; - } - std::unique_ptr input(TFile::Open(efficiencyPath.value.c_str(), "READ")); - if (!input || input->IsZombie()) { - LOGF(fatal, "Could not open efficiency file %s", efficiencyPath.value.c_str()); - return; - } - auto* source = dynamic_cast(input->Get("ccdb_object")); - if (!source || source->GetNdimensions() != 4) { - LOGF(fatal, "Efficiency object must be a 4D THn with axes eta, pT, centrality, z-vtx"); - } - localEfficiency.reset(dynamic_cast(source->Clone("eecEfficiency"))); - if (!localEfficiency) { - LOGF(fatal, "Could not clone the efficiency object from %s", efficiencyPath.value.c_str()); - } - efficiency = localEfficiency.get(); + if (cfgEfficiency.cfgEfficiencyPath.value.empty()) { + efficiencyLoaded = true; return; } - if (!efficiency || !ccdb->isCachedObjectValid(efficiencyPath.value, timestamp)) { - efficiency = ccdb->getForTimeStamp>(efficiencyPath.value, timestamp); - if (!efficiency || efficiency->GetNdimensions() != 4) { - LOGF(fatal, "Could not load a 4D efficiency correction from %s", efficiencyPath.value.c_str()); + + if (!cfgEfficiency.cfgUsePIDEfficiencies) { + efficiency = ccdb->getForTimeStamp(cfgEfficiency.cfgEfficiencyPath.value, timestamp); + if (!efficiency) { + LOGF(fatal, "Could not load efficiency histogram from %s", cfgEfficiency.cfgEfficiencyPath.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram from %s", cfgEfficiency.cfgEfficiencyPath.value.c_str()); + } else { + static constexpr std::array EfficiencySpeciesNames{"ch", "pi", "ka", "pr"}; + pidEfficiencies.reserve(EfficiencySpeciesNames.size()); + for (const auto& speciesName : EfficiencySpeciesNames) { + const std::string path = cfgEfficiency.cfgEfficiencyPath.value + "/" + speciesName; + pidEfficiencies.push_back(ccdb->getForTimeStamp(path, timestamp)); + if (!pidEfficiencies.back()) { + LOGF(fatal, "Could not load PID efficiency histogram from %s", path.c_str()); + } + LOGF(info, "Loaded PID efficiency histogram from %s", path.c_str()); } } + efficiencyLoaded = true; } void loadAcceptance(uint64_t timestamp, int runNumber) @@ -696,17 +694,20 @@ struct EnergyFlowGfw { acceptanceRunNumber = runNumber; } - double efficiencyWeight(float eta, float pt, float centrality, float posZ) const + double getEfficiency(float pt, int pid) const { - if (!efficiency) { + TH1* efficiencyHistogram = efficiency; + if (cfgEfficiency.cfgUsePIDEfficiencies.value) { + if (pidEfficiencies.empty()) { + return 1.; + } + efficiencyHistogram = pidEfficiencies[pid]; + } else if (!efficiencyHistogram) { return 1.; } - std::array bins{ - efficiency->GetAxis(0)->FindBin(eta), - efficiency->GetAxis(1)->FindBin(pt), - efficiency->GetAxis(2)->FindBin(centrality), - efficiency->GetAxis(3)->FindBin(posZ)}; - return efficiency->GetBinContent(bins.data()); + + const double value = efficiencyHistogram->GetBinContent(efficiencyHistogram->FindBin(pt)); + return value == 0. ? -1. : 1. / value; } template @@ -853,9 +854,10 @@ struct EnergyFlowGfw { gfw->Clear(); for (const auto& track : tracks) { - const int pid = energy.weightMode.value == PtWeight ? Unidentified : particleId(track); + const bool needsParticleId = energy.weightMode.value != PtWeight || cfgEfficiency.cfgUsePIDEfficiencies; + const int pid = needsParticleId ? particleId(track) : Unidentified; const double et = transverseEnergy(track, pid); - const double weff = efficiencyWeight(track.eta(), track.pt(), centrality, collision.posZ()); + const double weff = getEfficiency(track.pt(), pid); const double wacc = acceptance ? acceptance->getNUA(track.phi(), track.eta(), collision.posZ()) : 1.; if (!std::isfinite(et) || !std::isfinite(weff) || !std::isfinite(wacc) || et <= 0. || weff <= 0. || wacc <= 0.) { continue; From 3d2143e7b9e743875b78d19b15d1ec990c35f0b3 Mon Sep 17 00:00:00 2001 From: Emil Gorm Nielsen Date: Tue, 20 Oct 2026 22:53:59 +0200 Subject: [PATCH 3/3] Link missing library --- PWGCF/GenericFramework/Tasks/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGCF/GenericFramework/Tasks/CMakeLists.txt b/PWGCF/GenericFramework/Tasks/CMakeLists.txt index bc5feb0779c..90b65bdba93 100644 --- a/PWGCF/GenericFramework/Tasks/CMakeLists.txt +++ b/PWGCF/GenericFramework/Tasks/CMakeLists.txt @@ -31,5 +31,5 @@ o2physics_add_dpl_workflow(flow-gfw-nonflow o2physics_add_dpl_workflow(energy-flow-gfw SOURCES energyFlowGfw.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCCDB O2Physics::AnalysisCore O2Physics::GFWCore COMPONENT_NAME Analysis)