From 2303ff6edc4b3ba2e70ab8a30c98bc6523abce5a Mon Sep 17 00:00:00 2001 From: spolitan Date: Wed, 4 Mar 2026 18:49:14 +0100 Subject: [PATCH 1/5] [PWGHF] Add alternative FT0c centrality estimator in HF centrality and flow task --- PWGHF/Core/CentralityEstimation.h | 27 ++++++++++++++++++++++++ PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx | 6 +++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/PWGHF/Core/CentralityEstimation.h b/PWGHF/Core/CentralityEstimation.h index 71cdc0ebffd..12807b8c444 100644 --- a/PWGHF/Core/CentralityEstimation.h +++ b/PWGHF/Core/CentralityEstimation.h @@ -30,6 +30,7 @@ enum CentralityEstimator { FT0M, FV0A, NTracksPV, + FT0CVariant1, NCentralityEstimators }; @@ -43,6 +44,11 @@ concept HasFT0CCent = requires(T collision) { collision.centFT0C(); }; +template +concept HasFT0CVariant1Cent = requires(T collision) { + collision.centFT0CVariant1(); +}; + template concept HasFT0MCent = requires(T collision) { collision.centFT0M(); @@ -76,6 +82,15 @@ float getCentralityColl(const TCollision& collision) return collision.centFT0C(); } +/// Evaluate centrality/multiplicity percentile using FT0C variant 1 estimator +/// \param candidate is candidate +/// \return centrality/multiplicity percentile of the collision +template +float getCentralityColl(const TCollision& collision) +{ + return collision.centFT0CVariant1(); +} + /// Evaluate centrality/multiplicity percentile using FT0M estimator /// \param candidate is candidate /// \return centrality/multiplicity percentile of the collision @@ -144,6 +159,18 @@ float getCentralityColl(const TCollision& collision, const int centEstimator) } LOG(fatal) << "Collision does not have centFV0A()."; break; + case CentralityEstimator::NTracksPV: + if constexpr (HasNTracksPvCent) { + return collision.centNTPV(); + } + LOG(fatal) << "Collision does not have centNTPV()."; + break; + case CentralityEstimator::FT0CVariant1: + if constexpr (HasFT0CVariant1Cent) { + return collision.centFT0CVariant1(); + } + LOG(fatal) << "Collision does not have centFT0CVariant1()."; + break; default: LOG(fatal) << "Centrality estimator not valid. See CentralityEstimator for valid values."; break; diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index 46d7da749fc..8c20136f24e 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -109,7 +109,7 @@ struct HfTaskFlowCharmHadrons { Configurable harmonic{"harmonic", 2, "harmonic number"}; Configurable qVecDetector{"qVecDetector", 3, "Detector for Q vector estimation (FV0A: 0, FT0M: 1, FT0A: 2, FT0C: 3, TPC Pos: 4, TPC Neg: 5, TPC Tot: 6)"}; - Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4)"}; + Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4, NTracksPV: 5, FT0CVariant1: 6)"}; Configurable selectionFlag{"selectionFlag", 1, "Selection Flag for hadron (e.g. 1 for skimming, 3 for topo. and kine., 7 for PID)"}; Configurable centralityMin{"centralityMin", 0., "Minimum centrality accepted in SP/EP computation (not applied in resolution process)"}; Configurable centralityMax{"centralityMax", 100., "Maximum centrality accepted in SP/EP computation (not applied in resolution process)"}; @@ -146,7 +146,7 @@ struct HfTaskFlowCharmHadrons { using CandXic0DataWMl = soa::Filtered>; using CandD0DataWMl = soa::Filtered>; using CandD0Data = soa::Filtered>; - using CollsWithQvecs = soa::Join; + using CollsWithQvecs = soa::Join; using TracksWithExtra = soa::Join; Filter filterSelectDsCandidates = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlag || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlag; @@ -878,7 +878,7 @@ struct HfTaskFlowCharmHadrons { float const xQVecBTot = collision.qvecBTotRe(); float const yQVecBTot = collision.qvecBTotIm(); - centrality = o2::hf_centrality::getCentralityColl(collision, o2::hf_centrality::CentralityEstimator::FT0C); + centrality = o2::hf_centrality::getCentralityColl(collision, CentEstimator); if (storeResoOccu) { const auto occupancy = o2::hf_occupancy::getOccupancyColl(collision, occEstimator); registry.fill(HIST("trackOccVsFT0COcc"), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); From a389646aee1d850c0e80806186e060e7a6c4a2cc Mon Sep 17 00:00:00 2001 From: spolitan Date: Wed, 4 Mar 2026 19:03:29 +0100 Subject: [PATCH 2/5] Move from variant1 to variant2 --- PWGHF/Core/CentralityEstimation.h | 18 +++++++++--------- PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/PWGHF/Core/CentralityEstimation.h b/PWGHF/Core/CentralityEstimation.h index 12807b8c444..33ee20266f4 100644 --- a/PWGHF/Core/CentralityEstimation.h +++ b/PWGHF/Core/CentralityEstimation.h @@ -30,7 +30,7 @@ enum CentralityEstimator { FT0M, FV0A, NTracksPV, - FT0CVariant1, + FT0CVariant2, NCentralityEstimators }; @@ -45,8 +45,8 @@ concept HasFT0CCent = requires(T collision) { }; template -concept HasFT0CVariant1Cent = requires(T collision) { - collision.centFT0CVariant1(); +concept HasFT0CVariant2Cent = requires(T collision) { + collision.centFT0CVariant2(); }; template @@ -85,10 +85,10 @@ float getCentralityColl(const TCollision& collision) /// Evaluate centrality/multiplicity percentile using FT0C variant 1 estimator /// \param candidate is candidate /// \return centrality/multiplicity percentile of the collision -template +template float getCentralityColl(const TCollision& collision) { - return collision.centFT0CVariant1(); + return collision.centFT0CVariant2(); } /// Evaluate centrality/multiplicity percentile using FT0M estimator @@ -165,11 +165,11 @@ float getCentralityColl(const TCollision& collision, const int centEstimator) } LOG(fatal) << "Collision does not have centNTPV()."; break; - case CentralityEstimator::FT0CVariant1: - if constexpr (HasFT0CVariant1Cent) { - return collision.centFT0CVariant1(); + case CentralityEstimator::FT0CVariant2: + if constexpr (HasFT0CVariant2Cent) { + return collision.centFT0CVariant2(); } - LOG(fatal) << "Collision does not have centFT0CVariant1()."; + LOG(fatal) << "Collision does not have centFT0CVariant2()."; break; default: LOG(fatal) << "Centrality estimator not valid. See CentralityEstimator for valid values."; diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index 8c20136f24e..8bb259c33d8 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -109,7 +109,7 @@ struct HfTaskFlowCharmHadrons { Configurable harmonic{"harmonic", 2, "harmonic number"}; Configurable qVecDetector{"qVecDetector", 3, "Detector for Q vector estimation (FV0A: 0, FT0M: 1, FT0A: 2, FT0C: 3, TPC Pos: 4, TPC Neg: 5, TPC Tot: 6)"}; - Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4, NTracksPV: 5, FT0CVariant1: 6)"}; + Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4, NTracksPV: 5, FT0CVariant2: 6)"}; Configurable selectionFlag{"selectionFlag", 1, "Selection Flag for hadron (e.g. 1 for skimming, 3 for topo. and kine., 7 for PID)"}; Configurable centralityMin{"centralityMin", 0., "Minimum centrality accepted in SP/EP computation (not applied in resolution process)"}; Configurable centralityMax{"centralityMax", 100., "Maximum centrality accepted in SP/EP computation (not applied in resolution process)"}; @@ -146,7 +146,7 @@ struct HfTaskFlowCharmHadrons { using CandXic0DataWMl = soa::Filtered>; using CandD0DataWMl = soa::Filtered>; using CandD0Data = soa::Filtered>; - using CollsWithQvecs = soa::Join; + using CollsWithQvecs = soa::Join; using TracksWithExtra = soa::Join; Filter filterSelectDsCandidates = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlag || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlag; From 6acb21e76ec65bf7d85d41233d2cbcbde99c16c7 Mon Sep 17 00:00:00 2001 From: spolitan Date: Fri, 6 Mar 2026 20:00:19 +0100 Subject: [PATCH 3/5] [PWGHF] adding sparse for centrality estimation --- PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index 8bb259c33d8..55656590a19 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -124,6 +124,8 @@ struct HfTaskFlowCharmHadrons { Configurable storeEpCosSin{"storeEpCosSin", false, "Flag to store cos and sin of EP angle in ThnSparse"}; Configurable storeCandEta{"storeCandEta", false, "Flag to store candidates eta"}; Configurable storeCandSign{"storeCandSign", false, "Flag to store candidates sign"}; + Configurable storeCentSparse{"storeCentSparse", false, "Flag to store up to 4 centrality estimators comparison sparse (only applied in resolution process)"}; + Configurable> centEstimatorsForSparse{"centEstimatorsForSparse", {1, 2, 3, 4}, "Centrality estimators to be stored in the centrality sparse (FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4). Up to 4 estimators can be configured."}; Configurable occEstimator{"occEstimator", 0, "Occupancy estimation (0: None, 1: ITS, 2: FT0C)"}; Configurable saveEpResoHisto{"saveEpResoHisto", false, "Flag to save event plane resolution histogram"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -254,6 +256,12 @@ struct HfTaskFlowCharmHadrons { registry.add("hCentEventWithCand", "Centrality distributions with charm candidates;Cent;entries", HistType::kTH1F, {{100, 0.f, 100.f}}); registry.add("hCentEventWithCandInSigRegion", "Centrality distributions with charm candidates in signal range;Cent;entries", HistType::kTH1F, {{100, 0.f, 100.f}}); + if (storeCentSparse) { + std::vector axesCent = {thnAxisCent, thnAxisCent, thnAxisCent, thnAxisCent}; + registry.add("hSparseCentEstimators", "THn with different centrality estimators; Centrality 0; Centrality 1; Centrality 2; Centrality 3", {HistType::kTHnSparseF, axesCent}); + } + + if (occEstimator != 0) { registry.add("trackOccVsFT0COcc", "trackOccVsFT0COcc; trackOcc; FT0COcc", {HistType::kTH2F, {thnAxisOccupancyITS, thnAxisOccupancyFT0C}}); } @@ -890,6 +898,11 @@ struct HfTaskFlowCharmHadrons { occupancy, evtSelFlags[0], evtSelFlags[1], evtSelFlags[2], evtSelFlags[3], evtSelFlags[4]); } + if (storeCentSparse) { + registry.fill(HIST("hSparseCentEstimators"), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse[0]), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse[1]), + o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse[2]), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse[3])); + } + if (!isCollSelected(collision, bcs, centrality)) { // no selection on the centrality is applied, but on event selection flags return; From 064d4f1ed212fbe727552fe9000ade137acf7c86 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Fri, 6 Mar 2026 19:01:07 +0000 Subject: [PATCH 4/5] Please consider the following formatting changes --- PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index 55656590a19..e1dab690c85 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -261,7 +261,6 @@ struct HfTaskFlowCharmHadrons { registry.add("hSparseCentEstimators", "THn with different centrality estimators; Centrality 0; Centrality 1; Centrality 2; Centrality 3", {HistType::kTHnSparseF, axesCent}); } - if (occEstimator != 0) { registry.add("trackOccVsFT0COcc", "trackOccVsFT0COcc; trackOcc; FT0COcc", {HistType::kTH2F, {thnAxisOccupancyITS, thnAxisOccupancyFT0C}}); } From a7730d54e3b675a4f51d752042125d10ecb6dac2 Mon Sep 17 00:00:00 2001 From: spolitan Date: Fri, 6 Mar 2026 20:40:43 +0100 Subject: [PATCH 5/5] [PWGHF] fix bug --- PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index e1dab690c85..78462e10a73 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -148,7 +148,7 @@ struct HfTaskFlowCharmHadrons { using CandXic0DataWMl = soa::Filtered>; using CandD0DataWMl = soa::Filtered>; using CandD0Data = soa::Filtered>; - using CollsWithQvecs = soa::Join; + using CollsWithQvecs = soa::Join; using TracksWithExtra = soa::Join; Filter filterSelectDsCandidates = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlag || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlag; @@ -885,7 +885,7 @@ struct HfTaskFlowCharmHadrons { float const xQVecBTot = collision.qvecBTotRe(); float const yQVecBTot = collision.qvecBTotIm(); - centrality = o2::hf_centrality::getCentralityColl(collision, CentEstimator); + centrality = o2::hf_centrality::getCentralityColl(collision, centEstimator); if (storeResoOccu) { const auto occupancy = o2::hf_occupancy::getOccupancyColl(collision, occEstimator); registry.fill(HIST("trackOccVsFT0COcc"), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); @@ -898,8 +898,8 @@ struct HfTaskFlowCharmHadrons { } if (storeCentSparse) { - registry.fill(HIST("hSparseCentEstimators"), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse[0]), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse[1]), - o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse[2]), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse[3])); + registry.fill(HIST("hSparseCentEstimators"), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(0)), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(1)), + o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(2)), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(3))); } if (!isCollSelected(collision, bcs, centrality)) {