From 58ff59057511553b3ca85991dbc1311ae9cf6c26 Mon Sep 17 00:00:00 2001 From: Neelkamal Mallick Date: Wed, 30 Sep 2026 10:59:35 +0200 Subject: [PATCH 1/2] [PWGCF] JCorran: Add nonflow SPC correlators and a smaller Q-vector fill grid --- PWGCF/JCorran/Core/FlowJSPCAnalysis.cxx | 13 +++++++ PWGCF/JCorran/Core/FlowJSPCAnalysis.h | 36 +++++++++++++++++--- PWGCF/JCorran/Core/FlowJSPCObservables.h | 43 +++++++++++++++--------- PWGCF/JCorran/Core/JQVectors.h | 30 +++++++++++++---- PWGCF/JCorran/Tasks/flowJSPCAnalysis.cxx | 6 +++- 5 files changed, 99 insertions(+), 29 deletions(-) diff --git a/PWGCF/JCorran/Core/FlowJSPCAnalysis.cxx b/PWGCF/JCorran/Core/FlowJSPCAnalysis.cxx index 0c1927d9579..bbf74ac53da 100644 --- a/PWGCF/JCorran/Core/FlowJSPCAnalysis.cxx +++ b/PWGCF/JCorran/Core/FlowJSPCAnalysis.cxx @@ -125,6 +125,19 @@ void FlowJSPCAnalysis::calculateCorrelators(const int fCentBin) correlationDenom = 0.; weightCorrelationDenom = 0.; } + + // N_m = Re(Q_{0,1}); weight M_m. 3SPC → fN3, 4SPC → fN4. + if (mHistRegistry && qvecs) { + const double nSel = qvecs->QvectorQC[0][1].Re(); + const float centX = static_cast(fCentBin) + 0.5f; + if (nSel > 0.0 && std::isfinite(nSel)) { + if (mWhichSPC == 0 && fCorrelDenoms[2] > 0.0) { + mHistRegistry->fill(HIST("fN3"), centX, nSel, fCorrelDenoms[2]); + } else if (mWhichSPC == 1 && fCorrelDenoms[3] > 0.0) { + mHistRegistry->fill(HIST("fN4"), centX, nSel, fCorrelDenoms[3]); + } + } + } } void FlowJSPCAnalysis::fillHistograms(const int fCentBin, int ind, double cNum, double cDenom, double wNum, double wDenom) diff --git a/PWGCF/JCorran/Core/FlowJSPCAnalysis.h b/PWGCF/JCorran/Core/FlowJSPCAnalysis.h index 59a677dccd7..bdec9479b69 100644 --- a/PWGCF/JCorran/Core/FlowJSPCAnalysis.h +++ b/PWGCF/JCorran/Core/FlowJSPCAnalysis.h @@ -29,6 +29,7 @@ #include +#include #include #include #include @@ -42,6 +43,27 @@ class FlowJSPCAnalysis int getCentBin(float cValue); using JQVectorsT = JQVectors; + /// Fill-grid size for Q_{n,p}: (v8 * nPartDen)+1 harmonics, nPartDen+1 powers. + static constexpr uint32_t Nh3p = 49; // 3-particle SPC, 6-particle denominator + static constexpr uint32_t Nk3p = 7; + static constexpr uint32_t Nh4p = 65; // 4-particle SPC, 8-particle denominator + static constexpr uint32_t Nk4p = 9; + static constexpr uint32_t NhFull = 113; + static constexpr uint32_t NkFull = 15; + void qVectorGrid(int whichSPC, uint32_t& nhUse, uint32_t& nkUse) + { + mWhichSPC = whichSPC; + if (whichSPC == 0) { + nhUse = Nh3p; + nkUse = Nk3p; + } else if (whichSPC == 1) { + nhUse = Nh4p; + nkUse = Nk4p; + } else { + nhUse = NhFull; + nkUse = NkFull; + } + } inline void setQvectors(const JQVectorsT* _qvecs) { qvecs = _qvecs; } void correlation(int c_nPart, int c_nHarmo, int* harmo, double* correlData); void calculateCorrelators(const int fCentBin); @@ -57,6 +79,9 @@ class FlowJSPCAnalysis return; } mHistRegistry->add("FullCentrality", "FullCentrality", o2::framework::HistType::kTH1D, {{100, 0., 100.}}, true); + // Effective N_m per centrality class, weighted by M_m (arXiv:2606.10258 c0). + mHistRegistry->add("fN3", "Effective N_{3};centrality class;N_{3}", {o2::framework::HistType::kTProfile, {{9, 0., 9.}}}, true); + mHistRegistry->add("fN4", "Effective N_{4};centrality class;N_{4}", {o2::framework::HistType::kTProfile, {{9, 0., 9.}}}, true); mHistRegistry->add("Centrality_0/fResults", "Numerators and denominators", {o2::framework::HistType::kTProfile, {{24, 0., 24.}}}, true); mHistRegistry->add("Centrality_0/fCovResults", "Covariance N*D", {o2::framework::HistType::kTProfile, {{48, 0., 48.}}}, true); mHistRegistry->add("Centrality_0/phiBefore", "Phi before", {o2::framework::HistType::kTH1D, {{100, 0., o2::constants::math::TwoPI}}}, true); @@ -67,13 +92,13 @@ class FlowJSPCAnalysis } } - void setCorrSet(int obsInd, int harmo[8]) + void setCorrSet(int obsInd, int const harmo[8]) { for (int i = 0; i < 8; i++) { fHarmosArray[obsInd][i] = harmo[i]; } } - void setFullCorrSet(int harmo[12][8]) + void setFullCorrSet(int const harmo[12][8]) { memcpy(fHarmosArray, harmo, sizeof(int) * 12 * 8); } @@ -92,13 +117,14 @@ class FlowJSPCAnalysis private: const int mNqHarmos = 113; ///< Highest harmo for Q(n,p): (v8*14part)+1. const int mNqPowers = 15; ///< Max power for Q(n,p): 14part+1. - const JQVectorsT* qvecs; + const JQVectorsT* qvecs = nullptr; o2::framework::HistogramRegistry* mHistRegistry = nullptr; - int fHarmosArray[12][8]; + int fHarmosArray[12][8] = {{0}}; - double fCorrelDenoms[14]; + double fCorrelDenoms[14] = {0}; + int mWhichSPC = 0; ClassDefNV(FlowJSPCAnalysis, 1); }; diff --git a/PWGCF/JCorran/Core/FlowJSPCObservables.h b/PWGCF/JCorran/Core/FlowJSPCObservables.h index 440d70c8bf2..71d5011bf76 100644 --- a/PWGCF/JCorran/Core/FlowJSPCObservables.h +++ b/PWGCF/JCorran/Core/FlowJSPCObservables.h @@ -38,42 +38,53 @@ class FlowJSPCObservables switch (index) { case 0: { LOGF(info, "Computing three harmonic SPC"); - int harmonicArray01[maxNrComb][8] = { - {3, 6, -3, -3, 0, 0, 0, 0}, - {3, 4, -2, -2, 0, 0, 0, 0}, + // fResults slot j: num at 2j+0.5, denom at 2j+1.5. arXiv:2606.10258 nonflow refs in unused slots. + int const harmonicArray01[maxNrComb][8] = { + {3, 6, -3, -3, 0, 0, 0, 0}, // 0: C633 = + {3, 4, -2, -2, 0, 0, 0, 0}, // 1: C422 = {3, 8, -4, -4, 0, 0, 0, 0}, - {3, 2, 4, -6, 0, 0, 0, 0}, - {3, 2, 3, -5, 0, 0, 0, 0}, + {3, 2, 4, -6, 0, 0, 0, 0}, // 3: C246 = + {3, 2, 3, -5, 0, 0, 0, 0}, // 4: C235 = {3, 3, 4, -7, 0, 0, 0, 0}, // These are three harmonic SPC!! {3, 2, 5, -7, 0, 0, 0, 0}, // These are three harmonic SPC!! {3, 3, 5, -8, 0, 0, 0, 0}, // These are three harmonic SPC!! - {0, 6, -2, -2, -2, 0, 0, 0}, - {0, 2, -3, -4, 5, 0, 0, 0}, - {0, 2, -3, -3, 4, 0, 0, 0}, - {0, 3, 3, -2, -2, -2, 0, 0}}; + // {0, 6, -2, -2, -2, 0, 0, 0}, + // {0, 2, -3, -4, 5, 0, 0, 0}, + // {0, 2, -3, -3, 4, 0, 0, 0}, + // {0, 3, 3, -2, -2, -2, 0, 0}, + {3, 1, 1, -2, 0, 0, 0, 0}, // 8: C112 = , Eqs. (IV.7), (IV.18) + {3, 1, 2, -3, 0, 0, 0, 0}, // 9: C123 = , Eqs. (IV.8), (IV.18) + {0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0}}; memcpy(harmonicArray, harmonicArray01, sizeof(int) * maxNrComb * 8); } break; case 1: { LOGF(info, "Computing four harmonic SPC"); - int harmonicArray02[maxNrComb][8] = { - {4, 6, -2, -2, -2, 0, 0, 0}, + // fResults slot j: num at 2j+0.5, denom at 2j+1.5. arXiv:2606.10258: c1{4}=<<4>>-2<<2>>^2 after averaging, Eq. (IV.6). + int const harmonicArray02[maxNrComb][8] = { + {4, 6, -2, -2, -2, 0, 0, 0}, // 0: C6222 = {4, 2, -3, -4, 5, 0, 0, 0}, {4, 2, -3, -3, 4, 0, 0, 0}, {4, 2, 2, 3, -7, 0, 0, 0}, // These are three harmonic SPC!! {4, 2, 2, 4, -8, 0, 0, 0}, // These are three harmonic SPC!! {4, 2, 7, -4, -5, 0, 0, 0}, {4, 3, -4, -4, 5, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0}, + // {0, 0, 0, 0, 0, 0, 0, 0}, + // {0, 0, 0, 0, 0, 0, 0, 0}, + // {0, 0, 0, 0, 0, 0, 0, 0}, + // {0, 0, 0, 0, 0, 0, 0, 0}, + // {0, 0, 0, 0, 0, 0, 0, 0}, + {4, 1, 1, -1, -1, 0, 0, 0}, // 7: <<4>>_{1,1,-1,-1} for c1{4} + {2, 1, -1, 0, 0, 0, 0, 0}, // 8: <<2>>_{1,-1} = + {3, 1, 1, -2, 0, 0, 0, 0}, // 9: C112 on the 4-particle sample (mixed-order Eq. (IV.19)) {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}}; memcpy(harmonicArray, harmonicArray02, sizeof(int) * maxNrComb * 8); } break; case 2: { LOGF(info, "Computing five and six harmonic SPC"); - int harmonicArray03[maxNrComb][8] = { + int const harmonicArray03[maxNrComb][8] = { {5, 3, 3, -2, -2, -2, 0, 0}, {5, 2, 2, -3, 4, -5, 0, 0}, {5, 2, 3, 3, -4, -4, 0, 0}, @@ -90,7 +101,7 @@ class FlowJSPCObservables } break; case 3: { LOGF(info, "Computing slected five harmonic SPC"); - int harmonicArray04[maxNrComb][8] = { + int const harmonicArray04[maxNrComb][8] = { {5, 3, 3, -2, -2, -2, 0, 0}, {0, 2, 2, -3, 4, -5, 0, 0}, {5, 2, 3, 3, -4, -4, 0, 0}, diff --git a/PWGCF/JCorran/Core/JQVectors.h b/PWGCF/JCorran/Core/JQVectors.h index d0ba705c32f..aadb821fc2b 100644 --- a/PWGCF/JCorran/Core/JQVectors.h +++ b/PWGCF/JCorran/Core/JQVectors.h @@ -19,6 +19,8 @@ #include +#include +#include #include #include @@ -52,11 +54,16 @@ class JQVectors : public std::conditional_t, JQ using hasInvMass = decltype(std::declval().invMass()); template - inline void Calculate(JInputClass& inputInst, float etamin, float etamax, float massMin = 0.0f, float massMax = 999.9f) + inline void Calculate(JInputClass& inputInst, float etamin, float etamax, float massMin = 0.0f, float massMax = 999.9f, + uint32_t nhUse = nh, uint32_t nkUse = nk) { + // nhUse/nkUse limit the filled (harmonic, power) grid. Defaults keep the full template size. + const uint32_t nH = std::min(nhUse, nh); + const uint32_t nK = std::min(nkUse, nk); + // calculate Q-vector for QC method ( no subgroup ) - for (UInt_t ih = 0; ih < nh; ++ih) { - for (UInt_t ik = 0; ik < nk; ++ik) { + for (UInt_t ih = 0; ih < nH; ++ih) { + for (UInt_t ik = 0; ik < nK; ++ik) { QvectorQC[ih][ik] = Q(0, 0); if constexpr (gap) { for (UInt_t isub = 0; isub < 2; ++isub) @@ -64,7 +71,7 @@ class JQVectors : public std::conditional_t, JQ } } } - for (auto& track : inputInst) { + for (auto const& track : inputInst) { if (track.eta() < -etamax || track.eta() > etamax) continue; using JInputClassIter = typename JInputClass::iterator; @@ -74,10 +81,15 @@ class JQVectors : public std::conditional_t, JQ } UInt_t isub = (UInt_t)(track.eta() > 0.0); - for (UInt_t ih = 0; ih < nh; ++ih) { + const Double_t phi = track.phi(); + const Double_t c1 = TMath::Cos(phi); + const Double_t s1 = TMath::Sin(phi); + Double_t cn = 1.0; // cos(ih * phi), ih = 0 + Double_t sn = 0.0; // sin(ih * phi) + for (UInt_t ih = 0; ih < nH; ++ih) { Double_t tf = 1.0; - for (UInt_t ik = 0; ik < nk; ++ik) { - Q q(tf * TMath::Cos(ih * track.phi()), tf * TMath::Sin(ih * track.phi())); + for (UInt_t ik = 0; ik < nK; ++ik) { + Q q(tf * cn, tf * sn); QvectorQC[ih][ik] += q; if constexpr (gap) { @@ -90,6 +102,10 @@ class JQVectors : public std::conditional_t, JQ if constexpr (std::experimental::is_detected::value) tf *= track.weightEff(); } + const Double_t cnNext = cn * c1 - sn * s1; + const Double_t snNext = cn * s1 + sn * c1; + cn = cnNext; + sn = snNext; } } } diff --git a/PWGCF/JCorran/Tasks/flowJSPCAnalysis.cxx b/PWGCF/JCorran/Tasks/flowJSPCAnalysis.cxx index 6892ab58658..cfe7f931a39 100644 --- a/PWGCF/JCorran/Tasks/flowJSPCAnalysis.cxx +++ b/PWGCF/JCorran/Tasks/flowJSPCAnalysis.cxx @@ -109,6 +109,8 @@ struct flowJSPCAnalysis { std::unique_ptr multCutFormula; std::array multCutFormulaParamIndex; + uint32_t mNhUse = FlowJSPCAnalysis::NhFull; + uint32_t mNkUse = FlowJSPCAnalysis::NkFull; void init(InitContext const&) { @@ -118,6 +120,8 @@ struct flowJSPCAnalysis { spcObservables.setSPCObservables(cfgWhichSPC); spcAnalysis.setFullCorrSet(spcObservables.harmonicArray); + spcAnalysis.qVectorGrid(cfgWhichSPC, mNhUse, mNkUse); + LOGF(info, "Q-vector fill grid: nh=%u nk=%u (cfgWhichSPC=%d)", mNhUse, mNkUse, cfgWhichSPC.value); histManager.setHistRegistryQA(&qaHistRegistry); histManager.setDebugLog(false); @@ -186,7 +190,7 @@ struct flowJSPCAnalysis { if (cfgFillQA) histManager.fillEventQA<1>(collision, cBin, cent, nTracks); - jqvecs.Calculate(tracks, 0.0, cfgTrackCuts.cfgEtaMax); + jqvecs.Calculate(tracks, 0.0, cfgTrackCuts.cfgEtaMax, 0.0f, 999.9f, mNhUse, mNkUse); spcAnalysis.setQvectors(&jqvecs); spcAnalysis.calculateCorrelators(cBin); } From b42454f2189b600529b7ccefeb57390cfaa6bf7c Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Wed, 30 Sep 2026 09:04:59 +0000 Subject: [PATCH 2/2] Please consider the following formatting changes --- PWGCF/JCorran/Core/FlowJSPCAnalysis.h | 4 ++-- PWGCF/JCorran/Core/FlowJSPCObservables.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGCF/JCorran/Core/FlowJSPCAnalysis.h b/PWGCF/JCorran/Core/FlowJSPCAnalysis.h index bdec9479b69..97ddedc1af2 100644 --- a/PWGCF/JCorran/Core/FlowJSPCAnalysis.h +++ b/PWGCF/JCorran/Core/FlowJSPCAnalysis.h @@ -44,9 +44,9 @@ class FlowJSPCAnalysis using JQVectorsT = JQVectors; /// Fill-grid size for Q_{n,p}: (v8 * nPartDen)+1 harmonics, nPartDen+1 powers. - static constexpr uint32_t Nh3p = 49; // 3-particle SPC, 6-particle denominator + static constexpr uint32_t Nh3p = 49; // 3-particle SPC, 6-particle denominator static constexpr uint32_t Nk3p = 7; - static constexpr uint32_t Nh4p = 65; // 4-particle SPC, 8-particle denominator + static constexpr uint32_t Nh4p = 65; // 4-particle SPC, 8-particle denominator static constexpr uint32_t Nk4p = 9; static constexpr uint32_t NhFull = 113; static constexpr uint32_t NkFull = 15; diff --git a/PWGCF/JCorran/Core/FlowJSPCObservables.h b/PWGCF/JCorran/Core/FlowJSPCObservables.h index 71d5011bf76..e5db30a94e7 100644 --- a/PWGCF/JCorran/Core/FlowJSPCObservables.h +++ b/PWGCF/JCorran/Core/FlowJSPCObservables.h @@ -76,8 +76,8 @@ class FlowJSPCObservables // {0, 0, 0, 0, 0, 0, 0, 0}, // {0, 0, 0, 0, 0, 0, 0, 0}, {4, 1, 1, -1, -1, 0, 0, 0}, // 7: <<4>>_{1,1,-1,-1} for c1{4} - {2, 1, -1, 0, 0, 0, 0, 0}, // 8: <<2>>_{1,-1} = - {3, 1, 1, -2, 0, 0, 0, 0}, // 9: C112 on the 4-particle sample (mixed-order Eq. (IV.19)) + {2, 1, -1, 0, 0, 0, 0, 0}, // 8: <<2>>_{1,-1} = + {3, 1, 1, -2, 0, 0, 0, 0}, // 9: C112 on the 4-particle sample (mixed-order Eq. (IV.19)) {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}}; memcpy(harmonicArray, harmonicArray02, sizeof(int) * maxNrComb * 8);