From 4a781e6cf6830733b532752ead0a764a1e916ca6 Mon Sep 17 00:00:00 2001 From: Ankur Yadav Date: Mon, 13 Apr 2026 00:01:32 +0200 Subject: [PATCH 1/6] Declared all Qvector tables in a produceGroup. Added a process function to fill Qvector tables for Dielectrons. Fill RefFlow and QvectorExtra table with FT0C cumulants if the cfgFT0CCumulant is true. --- PWGDQ/TableProducer/tableMaker_withAssoc.cxx | 58 ++++++++++++++++++-- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx index adc962dc783..ccf5fa77ca8 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -186,8 +186,6 @@ struct TableMaker { Produces eventExtended; Produces eventVtxCov; Produces eventInfo; - Produces eventQvectorCentr; - Produces eventQvectorCentrExtra; Produces zdc; Produces fit; Produces multPV; @@ -208,6 +206,14 @@ struct TableMaker { Produces mftTrackExtra; Produces mftAssoc; + // Q-vector related tables, to be filled only if the user selects the corresponding option; since they are not needed for the skimming, we keep them in a separate group to avoid filling them when not needed + struct : ProducesGroup { + Produces eventQvectorCentr; + Produces eventQvectorCentrExtra; + Produces eventQvectorExtra; + Produces eventRefFlow; + } qvecGroup; + OutputObj fOutputList{"output"}; //! the histogram manager output list OutputObj fStatsList{"Statistics"}; //! skimming statistics @@ -288,6 +294,12 @@ struct TableMaker { Configurable fConfigSaveElectronSample{"cfgSaveElectronSample", false, "If true, only save electron sample"}; } fConfigPostCalibTPC; + // + struct : ConfigurableGroup { + Configurable fConfigFT0CCumulant{"cfgFT0CCumulant", false, + "If true, compute RefFlow cumulants from FT0C amplitudes (requires FT0s subscription)"}; + } fConfigQvector; + struct : ConfigurableGroup { // Track related options Configurable fPropTrack{"cfgPropTrack", true, "Propagate tracks to associated collision to recalculate DCA and momentum vector"}; @@ -1178,9 +1190,36 @@ struct TableMaker { eventInfo(collision.globalIndex()); if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionQvectCentr) > 0) { - eventQvectorCentr(collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.qvecFT0CRe(), collision.qvecFT0CIm(), collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.qvecFV0ARe(), collision.qvecFV0AIm(), collision.qvecTPCposRe(), collision.qvecTPCposIm(), collision.qvecTPCnegRe(), collision.qvecTPCnegIm(), + qvecGroup.eventQvectorCentr(collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.qvecFT0CRe(), collision.qvecFT0CIm(), collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.qvecFV0ARe(), collision.qvecFV0AIm(), collision.qvecTPCposRe(), collision.qvecTPCposIm(), collision.qvecTPCnegRe(), collision.qvecTPCnegIm(), collision.sumAmplFT0A(), collision.sumAmplFT0C(), collision.sumAmplFT0M(), collision.sumAmplFV0A(), collision.nTrkTPCpos(), collision.nTrkTPCneg()); - eventQvectorCentrExtra(collision.qvecTPCallRe(), collision.qvecTPCallIm(), collision.nTrkTPCall()); + qvecGroup.eventQvectorCentrExtra(collision.qvecTPCallRe(), collision.qvecTPCallIm(), collision.nTrkTPCall()); + + if (fConfigQvector.fConfigFT0CCumulant) { + // FT0C cumulants for RefFlow and QvectorExtra + float S11C = collision.sumAmplFT0C(); + float S12C = 0.f; + if constexpr (!std::is_same_v, std::nullptr_t>) { + if (collision.has_foundFT0()) { + auto ft0 = collision.foundFT0(); + for (auto amp : ft0.amplitudeC()) { + if (amp > 0.f) { + S12C += amp * amp; + } + } + } + } + float S21C = S11C * S11C; + float M11REF = S21C - S12C; + std::complex Q21C(collision.qvecFT0CRe() * S11C, collision.qvecFT0CIm() * S11C); + float CORR2REF = (std::norm(Q21C) - S12C) / M11REF; + + if (std::isnan(M11REF) || std::isinf(M11REF) || std::isnan(CORR2REF) || std::isinf(CORR2REF)) { + M11REF = 0.f; + CORR2REF = 0.f; + } + qvecGroup.eventRefFlow(M11REF, -9999, -9999, CORR2REF, -9999, -9999, VarManager::fgValues[VarManager::kCentFT0C]); + qvecGroup.eventQvectorExtra(-9999, -9999, -9999, -9999, S11C, S12C, -9999, -9999); + } } if constexpr ((TEventFillMap & VarManager::ObjTypes::Zdc) > 0) { @@ -1936,6 +1975,16 @@ struct TableMaker { fullSkimming(collisions, bcs, nullptr, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); } + // produce the barrel only DQ skimmed data model typically for Pb-Pb (with centrality), no subscribtion to the DQ event filter + void processPbPbBarrelOnlyWithQvect(MyEventsWithCentAndMultsQvect const& collisions, MyBCs const& bcs, + MyBarrelTracksWithCov const& tracksBarrel, + TrackAssoc const& trackAssocs, aod::FT0s& ft0s) + { + computeOccupancyEstimators(collisions, tracksPosWithCov, tracksNegWithCov, presliceWithCov, bcs); + computeCollMergingTag(collisions, tracksBarrel, presliceWithCov); + fullSkimming(collisions, bcs, nullptr, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, nullptr, ft0s, nullptr, nullptr); + } + // produce the barrel only DQ skimmed data model typically for Pb-Pb (with centrality), no TOF void processPbPbBarrelOnlyNoTOF(MyEventsWithCentAndMults const& collisions, MyBCs const& bcs, MyBarrelTracksWithCovNoTOF const& tracksBarrel, @@ -2038,6 +2087,7 @@ struct TableMaker { PROCESS_SWITCH(TableMaker, processPPMuonMFTWithMultsExtra, "Build muon + mft DQ skimmed data model typically for pp/p-Pb and UPC Pb-Pb", false); PROCESS_SWITCH(TableMaker, processPbPb, "Build full DQ skimmed data model typically for Pb-Pb, w/o event filtering", false); PROCESS_SWITCH(TableMaker, processPbPbBarrelOnly, "Build barrel only DQ skimmed data model typically for Pb-Pb, w/o event filtering", false); + PROCESS_SWITCH(TableMaker, processPbPbBarrelOnlyWithQvect, "Build barrel only DQ skimmed data model typically for Pb-Pb, w/o event filtering with event properties and flow", false); PROCESS_SWITCH(TableMaker, processPbPbBarrelOnlyNoTOF, "Build barrel only DQ skimmed data model typically for Pb-Pb, w/o event filtering, no TOF", false); PROCESS_SWITCH(TableMaker, processPbPbWithFilterBarrelOnly, "Build barrel only DQ skimmed data model typically for UPC Pb-Pb, w/ event filtering", false); PROCESS_SWITCH(TableMaker, processPbPbBarrelOnlyWithV0Bits, "Build barrel only DQ skimmed data model typically for Pb-Pb, w/ V0 bits, w/o event filtering", false); From 6ed8f9e3548363fef83731ab0ad07ac0c3b59168 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Mon, 13 Apr 2026 09:27:44 +0000 Subject: [PATCH 2/6] Please consider the following formatting changes --- PWGDQ/TableProducer/tableMaker_withAssoc.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx index ccf5fa77ca8..b49b2a286cb 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -294,10 +294,10 @@ struct TableMaker { Configurable fConfigSaveElectronSample{"cfgSaveElectronSample", false, "If true, only save electron sample"}; } fConfigPostCalibTPC; - // + // struct : ConfigurableGroup { Configurable fConfigFT0CCumulant{"cfgFT0CCumulant", false, - "If true, compute RefFlow cumulants from FT0C amplitudes (requires FT0s subscription)"}; + "If true, compute RefFlow cumulants from FT0C amplitudes (requires FT0s subscription)"}; } fConfigQvector; struct : ConfigurableGroup { @@ -1191,7 +1191,7 @@ struct TableMaker { if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionQvectCentr) > 0) { qvecGroup.eventQvectorCentr(collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.qvecFT0CRe(), collision.qvecFT0CIm(), collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.qvecFV0ARe(), collision.qvecFV0AIm(), collision.qvecTPCposRe(), collision.qvecTPCposIm(), collision.qvecTPCnegRe(), collision.qvecTPCnegIm(), - collision.sumAmplFT0A(), collision.sumAmplFT0C(), collision.sumAmplFT0M(), collision.sumAmplFV0A(), collision.nTrkTPCpos(), collision.nTrkTPCneg()); + collision.sumAmplFT0A(), collision.sumAmplFT0C(), collision.sumAmplFT0M(), collision.sumAmplFV0A(), collision.nTrkTPCpos(), collision.nTrkTPCneg()); qvecGroup.eventQvectorCentrExtra(collision.qvecTPCallRe(), collision.qvecTPCallIm(), collision.nTrkTPCall()); if (fConfigQvector.fConfigFT0CCumulant) { @@ -1212,7 +1212,7 @@ struct TableMaker { float M11REF = S21C - S12C; std::complex Q21C(collision.qvecFT0CRe() * S11C, collision.qvecFT0CIm() * S11C); float CORR2REF = (std::norm(Q21C) - S12C) / M11REF; - + if (std::isnan(M11REF) || std::isinf(M11REF) || std::isnan(CORR2REF) || std::isinf(CORR2REF)) { M11REF = 0.f; CORR2REF = 0.f; @@ -1977,8 +1977,8 @@ struct TableMaker { // produce the barrel only DQ skimmed data model typically for Pb-Pb (with centrality), no subscribtion to the DQ event filter void processPbPbBarrelOnlyWithQvect(MyEventsWithCentAndMultsQvect const& collisions, MyBCs const& bcs, - MyBarrelTracksWithCov const& tracksBarrel, - TrackAssoc const& trackAssocs, aod::FT0s& ft0s) + MyBarrelTracksWithCov const& tracksBarrel, + TrackAssoc const& trackAssocs, aod::FT0s& ft0s) { computeOccupancyEstimators(collisions, tracksPosWithCov, tracksNegWithCov, presliceWithCov, bcs); computeCollMergingTag(collisions, tracksBarrel, presliceWithCov); From 371c9241b89f544829fd771a8a194b4c789640b0 Mon Sep 17 00:00:00 2001 From: Ankur Yadav Date: Mon, 13 Apr 2026 17:38:40 +0200 Subject: [PATCH 3/6] Qvector-tables shall be filled for all PbPb processes (except for processPbPbWithFilterBarrelOnly). Added a configurable for Qvector calibration path. The tables shall only be filled if the calibrations are available --- PWGDQ/TableProducer/tableMaker_withAssoc.cxx | 128 +++++++++++-------- 1 file changed, 73 insertions(+), 55 deletions(-) diff --git a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx index b49b2a286cb..442f2b3cb9a 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -294,10 +294,10 @@ struct TableMaker { Configurable fConfigSaveElectronSample{"cfgSaveElectronSample", false, "If true, only save electron sample"}; } fConfigPostCalibTPC; - // + // struct : ConfigurableGroup { - Configurable fConfigFT0CCumulant{"cfgFT0CCumulant", false, - "If true, compute RefFlow cumulants from FT0C amplitudes (requires FT0s subscription)"}; + Configurable fConfigFT0CCumulant{"cfgFT0CCumulant", false, "If true, compute RefFlow cumulants from FT0C amplitudes (requires FT0s subscription)"}; + Configurable fConfigQvecCalibPath{"cfgQvecCalibPath","Analysis/EventPlane/QVecCorrections","CCDB path for qvector calibration objects; used only to check availability per run"}; } fConfigQvector; struct : ConfigurableGroup { @@ -335,6 +335,7 @@ struct TableMaker { bool fDoDetailedQA = false; // Bool to set detailed QA true, if QA is set true int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. + bool fQvectCalibAvailable = false; // Whether the Q-vector calibration is available for the current run // maps used to store index info; NOTE: std::map are sorted in ascending order by default (needed for track to collision indices) std::map fCollIndexMap; // key: old collision index, value: skimmed collision index @@ -479,7 +480,11 @@ struct TableMaker { } // Check whether we have to define barrel or muon histograms +<<<<<<< HEAD bool enableBarrelHistos = (context.mOptions.get("processPP") || context.mOptions.get("processPPWithFilter") || context.mOptions.get("processPPWithFilterBarrelOnly") || context.mOptions.get("processPPBarrelOnly") || +======= + bool enableBarrelHistos = (context.mOptions.get("processPPWithFilter") || context.mOptions.get("processPPWithFilterBarrelOnly") || context.mOptions.get("processPPBarrelOnly") || +>>>>>>> daa02bd72 (Qvector-tables shall be filled for all PbPb processes (except for processPbPbWithFilterBarrelOnly). Added a configurable for Qvector calibration path. The tables shall only be filled if the calibrations are available) context.mOptions.get("processPbPb") || context.mOptions.get("processPbPbBarrelOnly") || context.mOptions.get("processPbPbBarrelOnlyWithV0Bits") || context.mOptions.get("processPbPbBarrelOnlyWithV0BitsNoTOF")) || context.mOptions.get("processPbPbWithFilterBarrelOnly") || context.mOptions.get("processPPBarrelOnlyWithV0s") || context.mOptions.get("processPbPbBarrelOnlyNoTOF"); @@ -1190,38 +1195,39 @@ struct TableMaker { eventInfo(collision.globalIndex()); if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionQvectCentr) > 0) { - qvecGroup.eventQvectorCentr(collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.qvecFT0CRe(), collision.qvecFT0CIm(), collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.qvecFV0ARe(), collision.qvecFV0AIm(), collision.qvecTPCposRe(), collision.qvecTPCposIm(), collision.qvecTPCnegRe(), collision.qvecTPCnegIm(), - collision.sumAmplFT0A(), collision.sumAmplFT0C(), collision.sumAmplFT0M(), collision.sumAmplFV0A(), collision.nTrkTPCpos(), collision.nTrkTPCneg()); - qvecGroup.eventQvectorCentrExtra(collision.qvecTPCallRe(), collision.qvecTPCallIm(), collision.nTrkTPCall()); - - if (fConfigQvector.fConfigFT0CCumulant) { - // FT0C cumulants for RefFlow and QvectorExtra - float S11C = collision.sumAmplFT0C(); - float S12C = 0.f; - if constexpr (!std::is_same_v, std::nullptr_t>) { - if (collision.has_foundFT0()) { - auto ft0 = collision.foundFT0(); - for (auto amp : ft0.amplitudeC()) { - if (amp > 0.f) { - S12C += amp * amp; + if (fQvectCalibAvailable) { + qvecGroup.eventQvectorCentr(collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.qvecFT0CRe(), collision.qvecFT0CIm(), collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.qvecFV0ARe(), collision.qvecFV0AIm(), collision.qvecTPCposRe(), collision.qvecTPCposIm(), collision.qvecTPCnegRe(), collision.qvecTPCnegIm(), + collision.sumAmplFT0A(), collision.sumAmplFT0C(), collision.sumAmplFT0M(), collision.sumAmplFV0A(), collision.nTrkTPCpos(), collision.nTrkTPCneg()); + qvecGroup.eventQvectorCentrExtra(collision.qvecTPCallRe(), collision.qvecTPCallIm(), collision.nTrkTPCall()); + + if (fConfigQvector.fConfigFT0CCumulant) { + // FT0C cumulants for RefFlow and QvectorExtra + float S11C = collision.sumAmplFT0C(); + float S12C = 0.f; + if constexpr (!std::is_same_v, std::nullptr_t>) { + if (collision.has_foundFT0()) { + auto ft0 = collision.foundFT0(); + for (auto amp : ft0.amplitudeC()) { + if (amp > 0.f) { + S12C += amp * amp; + } } } } + float S21C = S11C * S11C; + float M11REF = S21C - S12C; + std::complex Q21C(collision.qvecFT0CRe() * S11C, collision.qvecFT0CIm() * S11C); + float CORR2REF = (std::norm(Q21C) - S12C) / M11REF; + + if (std::isnan(M11REF) || std::isinf(M11REF) || std::isnan(CORR2REF) || std::isinf(CORR2REF)) { + M11REF = 0.f; + CORR2REF = 0.f; + } + qvecGroup.eventRefFlow(M11REF, -9999, -9999, CORR2REF, -9999, -9999, VarManager::fgValues[VarManager::kCentFT0C]); + qvecGroup.eventQvectorExtra(-9999, -9999, -9999, -9999, S11C, S12C, -9999, -9999); } - float S21C = S11C * S11C; - float M11REF = S21C - S12C; - std::complex Q21C(collision.qvecFT0CRe() * S11C, collision.qvecFT0CIm() * S11C); - float CORR2REF = (std::norm(Q21C) - S12C) / M11REF; - - if (std::isnan(M11REF) || std::isinf(M11REF) || std::isnan(CORR2REF) || std::isinf(CORR2REF)) { - M11REF = 0.f; - CORR2REF = 0.f; - } - qvecGroup.eventRefFlow(M11REF, -9999, -9999, CORR2REF, -9999, -9999, VarManager::fgValues[VarManager::kCentFT0C]); - qvecGroup.eventQvectorExtra(-9999, -9999, -9999, -9999, S11C, S12C, -9999, -9999); } } - if constexpr ((TEventFillMap & VarManager::ObjTypes::Zdc) > 0) { if constexpr ((TEventFillMap & VarManager::ObjTypes::RapidityGapFilter) > 0) { // The DQRapidityGapFilter contains the index of the bc we want to get ZDC info from @@ -1771,6 +1777,29 @@ struct TableMaker { } std::map metadataRCT, header; header = fCCDBApi.retrieveHeaders(Form("RCT/Info/RunInformation/%i", bcs.begin().runNumber()), metadataRCT, -1); + + // Check if qvector calibration objects are available in CCDB for this run + if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionQvectCentr) > 0) { + std::map metadataQvect; + const std::array subfolders = {"v2", "v3", "v4"}; + bool anyFound = false; + for (const auto& sub : subfolders) { + std::string fullPath = fConfigQvector.fConfigQvecCalibPath.value + "/" + sub; + auto headers = fCCDBApi.retrieveHeaders(fullPath, metadataQvect, bcs.begin().timestamp()); + if (headers.empty()) { + LOG(warn) << "Qvector calibration not found at CCDB path '" << fullPath + << "' for run " << bcs.begin().runNumber(); + } else { + anyFound = true; + } + } + fQvectCalibAvailable = anyFound; + if (!fQvectCalibAvailable) { + LOG(warn) << "No qvector calibration found in any subfolder under '" + << fConfigQvector.fConfigQvecCalibPath.value + << "' — qvector tables will not be filled for this run."; + } + } uint64_t sor = std::atol(header["SOR"].c_str()); uint64_t eor = std::atol(header["EOR"].c_str()); VarManager::SetSORandEOR(sor, eor); @@ -1956,43 +1985,33 @@ struct TableMaker { } // produce the full DQ skimmed data model typically for Pb-Pb (with centrality), no subscribtion to the DQ event filter - void processPbPb(MyEventsWithCentAndMults const& collisions, MyBCs const& bcs, + void processPbPb(MyEventsWithCentAndMultsQvect const& collisions, MyBCs const& bcs, MyBarrelTracksWithCov const& tracksBarrel, MyMuonsWithCov const& muons, MFTTracks const& mftTracks, TrackAssoc const& trackAssocs, FwdTrackAssoc const& fwdTrackAssocs, - MFTTrackAssoc const& mftAssocs) + MFTTrackAssoc const& mftAssocs, aod::FT0s& ft0s, aod::FV0As& fv0as, aod::FDDs& fdds) { - fullSkimming(collisions, bcs, nullptr, tracksBarrel, muons, mftTracks, trackAssocs, fwdTrackAssocs, mftAssocs, nullptr, nullptr, nullptr, nullptr); + fullSkimming(collisions, bcs, nullptr, tracksBarrel, muons, mftTracks, trackAssocs, fwdTrackAssocs, mftAssocs, nullptr, ft0s, fv0as, fdds); } // produce the barrel only DQ skimmed data model typically for Pb-Pb (with centrality), no subscribtion to the DQ event filter - void processPbPbBarrelOnly(MyEventsWithCentAndMults const& collisions, MyBCs const& bcs, + void processPbPbBarrelOnly(MyEventsWithCentAndMultsQvect const& collisions, MyBCs const& bcs, MyBarrelTracksWithCov const& tracksBarrel, - TrackAssoc const& trackAssocs) + TrackAssoc const& trackAssocs, aod::FT0s& ft0s, aod::FV0As& fv0as, aod::FDDs& fdds) { computeOccupancyEstimators(collisions, tracksPosWithCov, tracksNegWithCov, presliceWithCov, bcs); computeCollMergingTag(collisions, tracksBarrel, presliceWithCov); - fullSkimming(collisions, bcs, nullptr, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); - } - - // produce the barrel only DQ skimmed data model typically for Pb-Pb (with centrality), no subscribtion to the DQ event filter - void processPbPbBarrelOnlyWithQvect(MyEventsWithCentAndMultsQvect const& collisions, MyBCs const& bcs, - MyBarrelTracksWithCov const& tracksBarrel, - TrackAssoc const& trackAssocs, aod::FT0s& ft0s) - { - computeOccupancyEstimators(collisions, tracksPosWithCov, tracksNegWithCov, presliceWithCov, bcs); - computeCollMergingTag(collisions, tracksBarrel, presliceWithCov); - fullSkimming(collisions, bcs, nullptr, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, nullptr, ft0s, nullptr, nullptr); + fullSkimming(collisions, bcs, nullptr, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, nullptr, ft0s, fv0as, fdds); } // produce the barrel only DQ skimmed data model typically for Pb-Pb (with centrality), no TOF - void processPbPbBarrelOnlyNoTOF(MyEventsWithCentAndMults const& collisions, MyBCs const& bcs, + void processPbPbBarrelOnlyNoTOF(MyEventsWithCentAndMultsQvect const& collisions, MyBCs const& bcs, MyBarrelTracksWithCovNoTOF const& tracksBarrel, - TrackAssoc const& trackAssocs) + TrackAssoc const& trackAssocs, aod::FT0s& ft0s, aod::FV0As& fv0as, aod::FDDs& fdds) { computeOccupancyEstimators(collisions, tracksPosWithCovNoTOF, tracksNegWithCovNoTOF, presliceWithCovNoTOF, bcs); computeCollMergingTag(collisions, tracksBarrel, presliceWithCovNoTOF); - fullSkimming(collisions, bcs, nullptr, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); + fullSkimming(collisions, bcs, nullptr, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, nullptr, ft0s, fv0as, fdds); } // produce the barrel-only DQ skimmed data model typically for UPC Pb-Pb (no centrality), subscribe to the DQ rapidity gap event filter (filter-PbPb) @@ -2006,23 +2025,23 @@ struct TableMaker { } // produce the barrel only DQ skimmed data model typically for Pb-Pb (with centrality), no subscribtion to the DQ event filter - void processPbPbBarrelOnlyWithV0Bits(MyEventsWithCentAndMults const& collisions, MyBCs const& bcs, + void processPbPbBarrelOnlyWithV0Bits(MyEventsWithCentAndMultsQvect const& collisions, MyBCs const& bcs, MyBarrelTracksWithV0Bits const& tracksBarrel, - TrackAssoc const& trackAssocs) + TrackAssoc const& trackAssocs, aod::FT0s& ft0s, aod::FV0As& fv0as, aod::FDDs& fdds) { computeOccupancyEstimators(collisions, tracksPos, tracksNeg, preslice, bcs); computeCollMergingTag(collisions, tracksBarrel, preslice); - fullSkimming(collisions, bcs, nullptr, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); + fullSkimming(collisions, bcs, nullptr, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, nullptr, ft0s, fv0as, fdds); } // produce the barrel only DQ skimmed data model typically for Pb-Pb (with centrality), no subscribtion to the DQ event filter - void processPbPbBarrelOnlyWithV0BitsNoTOF(MyEventsWithCentAndMults const& collisions, MyBCs const& bcs, + void processPbPbBarrelOnlyWithV0BitsNoTOF(MyEventsWithCentAndMultsQvect const& collisions, MyBCs const& bcs, MyBarrelTracksWithV0BitsNoTOF const& tracksBarrel, - TrackAssoc const& trackAssocs) + TrackAssoc const& trackAssocs, aod::FT0s& ft0s, aod::FV0As& fv0as, aod::FDDs& fdds) { computeOccupancyEstimators(collisions, tracksPosNoTOF, tracksNegNoTOF, presliceNoTOF, bcs); computeCollMergingTag(collisions, tracksBarrel, presliceNoTOF); - fullSkimming(collisions, bcs, nullptr, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); + fullSkimming(collisions, bcs, nullptr, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, nullptr, ft0s, fv0as, fdds); } // produce the muon only DQ skimmed data model typically for Pb-Pb (with centrality), no subscribtion to the DQ event filter @@ -2087,7 +2106,6 @@ struct TableMaker { PROCESS_SWITCH(TableMaker, processPPMuonMFTWithMultsExtra, "Build muon + mft DQ skimmed data model typically for pp/p-Pb and UPC Pb-Pb", false); PROCESS_SWITCH(TableMaker, processPbPb, "Build full DQ skimmed data model typically for Pb-Pb, w/o event filtering", false); PROCESS_SWITCH(TableMaker, processPbPbBarrelOnly, "Build barrel only DQ skimmed data model typically for Pb-Pb, w/o event filtering", false); - PROCESS_SWITCH(TableMaker, processPbPbBarrelOnlyWithQvect, "Build barrel only DQ skimmed data model typically for Pb-Pb, w/o event filtering with event properties and flow", false); PROCESS_SWITCH(TableMaker, processPbPbBarrelOnlyNoTOF, "Build barrel only DQ skimmed data model typically for Pb-Pb, w/o event filtering, no TOF", false); PROCESS_SWITCH(TableMaker, processPbPbWithFilterBarrelOnly, "Build barrel only DQ skimmed data model typically for UPC Pb-Pb, w/ event filtering", false); PROCESS_SWITCH(TableMaker, processPbPbBarrelOnlyWithV0Bits, "Build barrel only DQ skimmed data model typically for Pb-Pb, w/ V0 bits, w/o event filtering", false); From fecf39851749510148b4807aa86c497b78d87e57 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Mon, 13 Apr 2026 16:05:15 +0000 Subject: [PATCH 4/6] Please consider the following formatting changes --- PWGDQ/TableProducer/tableMaker_withAssoc.cxx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx index 442f2b3cb9a..7f6c2cebe29 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -294,10 +294,10 @@ struct TableMaker { Configurable fConfigSaveElectronSample{"cfgSaveElectronSample", false, "If true, only save electron sample"}; } fConfigPostCalibTPC; - // + // struct : ConfigurableGroup { Configurable fConfigFT0CCumulant{"cfgFT0CCumulant", false, "If true, compute RefFlow cumulants from FT0C amplitudes (requires FT0s subscription)"}; - Configurable fConfigQvecCalibPath{"cfgQvecCalibPath","Analysis/EventPlane/QVecCorrections","CCDB path for qvector calibration objects; used only to check availability per run"}; + Configurable fConfigQvecCalibPath{"cfgQvecCalibPath", "Analysis/EventPlane/QVecCorrections", "CCDB path for qvector calibration objects; used only to check availability per run"}; } fConfigQvector; struct : ConfigurableGroup { @@ -335,7 +335,7 @@ struct TableMaker { bool fDoDetailedQA = false; // Bool to set detailed QA true, if QA is set true int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. - bool fQvectCalibAvailable = false; // Whether the Q-vector calibration is available for the current run + bool fQvectCalibAvailable = false; // Whether the Q-vector calibration is available for the current run // maps used to store index info; NOTE: std::map are sorted in ascending order by default (needed for track to collision indices) std::map fCollIndexMap; // key: old collision index, value: skimmed collision index @@ -1197,7 +1197,7 @@ struct TableMaker { if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionQvectCentr) > 0) { if (fQvectCalibAvailable) { qvecGroup.eventQvectorCentr(collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.qvecFT0CRe(), collision.qvecFT0CIm(), collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.qvecFV0ARe(), collision.qvecFV0AIm(), collision.qvecTPCposRe(), collision.qvecTPCposIm(), collision.qvecTPCnegRe(), collision.qvecTPCnegIm(), - collision.sumAmplFT0A(), collision.sumAmplFT0C(), collision.sumAmplFT0M(), collision.sumAmplFV0A(), collision.nTrkTPCpos(), collision.nTrkTPCneg()); + collision.sumAmplFT0A(), collision.sumAmplFT0C(), collision.sumAmplFT0M(), collision.sumAmplFV0A(), collision.nTrkTPCpos(), collision.nTrkTPCneg()); qvecGroup.eventQvectorCentrExtra(collision.qvecTPCallRe(), collision.qvecTPCallIm(), collision.nTrkTPCall()); if (fConfigQvector.fConfigFT0CCumulant) { @@ -1218,7 +1218,7 @@ struct TableMaker { float M11REF = S21C - S12C; std::complex Q21C(collision.qvecFT0CRe() * S11C, collision.qvecFT0CIm() * S11C); float CORR2REF = (std::norm(Q21C) - S12C) / M11REF; - + if (std::isnan(M11REF) || std::isinf(M11REF) || std::isnan(CORR2REF) || std::isinf(CORR2REF)) { M11REF = 0.f; CORR2REF = 0.f; @@ -1777,7 +1777,7 @@ struct TableMaker { } std::map metadataRCT, header; header = fCCDBApi.retrieveHeaders(Form("RCT/Info/RunInformation/%i", bcs.begin().runNumber()), metadataRCT, -1); - + // Check if qvector calibration objects are available in CCDB for this run if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionQvectCentr) > 0) { std::map metadataQvect; @@ -1786,10 +1786,10 @@ struct TableMaker { for (const auto& sub : subfolders) { std::string fullPath = fConfigQvector.fConfigQvecCalibPath.value + "/" + sub; auto headers = fCCDBApi.retrieveHeaders(fullPath, metadataQvect, bcs.begin().timestamp()); - if (headers.empty()) { - LOG(warn) << "Qvector calibration not found at CCDB path '" << fullPath - << "' for run " << bcs.begin().runNumber(); - } else { + if (headers.empty()) { + LOG(warn) << "Qvector calibration not found at CCDB path '" << fullPath + << "' for run " << bcs.begin().runNumber(); + } else { anyFound = true; } } From 1ed03d125c9a503d531d7dd1d6cc34d700fbc567 Mon Sep 17 00:00:00 2001 From: Ankur Yadav Date: Tue, 14 Apr 2026 11:06:07 +0200 Subject: [PATCH 5/6] Removed the ccdb check for q-vector calib objects from tableMaker_withAssoc. Just use a bool configurable to check if they exist --- PWGDQ/TableProducer/tableMaker_withAssoc.cxx | 28 ++------------------ 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx index 7f6c2cebe29..8a9f622c3cc 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -297,7 +297,7 @@ struct TableMaker { // struct : ConfigurableGroup { Configurable fConfigFT0CCumulant{"cfgFT0CCumulant", false, "If true, compute RefFlow cumulants from FT0C amplitudes (requires FT0s subscription)"}; - Configurable fConfigQvecCalibPath{"cfgQvecCalibPath", "Analysis/EventPlane/QVecCorrections", "CCDB path for qvector calibration objects; used only to check availability per run"}; + Configurable fConfigQvectCalibAvailable{"cfgQvectCalibAvailable", false, "If true, qvector calibration objects are available in CCDB for this run"}; } fConfigQvector; struct : ConfigurableGroup { @@ -335,7 +335,6 @@ struct TableMaker { bool fDoDetailedQA = false; // Bool to set detailed QA true, if QA is set true int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. - bool fQvectCalibAvailable = false; // Whether the Q-vector calibration is available for the current run // maps used to store index info; NOTE: std::map are sorted in ascending order by default (needed for track to collision indices) std::map fCollIndexMap; // key: old collision index, value: skimmed collision index @@ -1195,7 +1194,7 @@ struct TableMaker { eventInfo(collision.globalIndex()); if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionQvectCentr) > 0) { - if (fQvectCalibAvailable) { + if (fConfigQvector.fConfigQvectCalibAvailable) { qvecGroup.eventQvectorCentr(collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.qvecFT0CRe(), collision.qvecFT0CIm(), collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.qvecFV0ARe(), collision.qvecFV0AIm(), collision.qvecTPCposRe(), collision.qvecTPCposIm(), collision.qvecTPCnegRe(), collision.qvecTPCnegIm(), collision.sumAmplFT0A(), collision.sumAmplFT0C(), collision.sumAmplFT0M(), collision.sumAmplFV0A(), collision.nTrkTPCpos(), collision.nTrkTPCneg()); qvecGroup.eventQvectorCentrExtra(collision.qvecTPCallRe(), collision.qvecTPCallIm(), collision.nTrkTPCall()); @@ -1777,29 +1776,6 @@ struct TableMaker { } std::map metadataRCT, header; header = fCCDBApi.retrieveHeaders(Form("RCT/Info/RunInformation/%i", bcs.begin().runNumber()), metadataRCT, -1); - - // Check if qvector calibration objects are available in CCDB for this run - if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionQvectCentr) > 0) { - std::map metadataQvect; - const std::array subfolders = {"v2", "v3", "v4"}; - bool anyFound = false; - for (const auto& sub : subfolders) { - std::string fullPath = fConfigQvector.fConfigQvecCalibPath.value + "/" + sub; - auto headers = fCCDBApi.retrieveHeaders(fullPath, metadataQvect, bcs.begin().timestamp()); - if (headers.empty()) { - LOG(warn) << "Qvector calibration not found at CCDB path '" << fullPath - << "' for run " << bcs.begin().runNumber(); - } else { - anyFound = true; - } - } - fQvectCalibAvailable = anyFound; - if (!fQvectCalibAvailable) { - LOG(warn) << "No qvector calibration found in any subfolder under '" - << fConfigQvector.fConfigQvecCalibPath.value - << "' — qvector tables will not be filled for this run."; - } - } uint64_t sor = std::atol(header["SOR"].c_str()); uint64_t eor = std::atol(header["EOR"].c_str()); VarManager::SetSORandEOR(sor, eor); From de94171936dcbc0d31c80ef3ff90800545c3b02f Mon Sep 17 00:00:00 2001 From: Ankur Yadav Date: Sun, 19 Apr 2026 20:58:18 +0200 Subject: [PATCH 6/6] Removed the FT0C cumulant calculation from TableMaker_withAssociation and implemented it in dqFlow which still has the cumulant calculation for froward rapidity using GFW to keep all cumulant calculations in one place. New process function in dqFlow for FT0C cumulant --- PWGDQ/TableProducer/tableMaker_withAssoc.cxx | 34 ------------ PWGDQ/Tasks/dqFlow.cxx | 54 ++++++++++++++++++++ 2 files changed, 54 insertions(+), 34 deletions(-) diff --git a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx index 8a9f622c3cc..2a26527ce36 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -210,8 +210,6 @@ struct TableMaker { struct : ProducesGroup { Produces eventQvectorCentr; Produces eventQvectorCentrExtra; - Produces eventQvectorExtra; - Produces eventRefFlow; } qvecGroup; OutputObj fOutputList{"output"}; //! the histogram manager output list @@ -296,7 +294,6 @@ struct TableMaker { // struct : ConfigurableGroup { - Configurable fConfigFT0CCumulant{"cfgFT0CCumulant", false, "If true, compute RefFlow cumulants from FT0C amplitudes (requires FT0s subscription)"}; Configurable fConfigQvectCalibAvailable{"cfgQvectCalibAvailable", false, "If true, qvector calibration objects are available in CCDB for this run"}; } fConfigQvector; @@ -479,11 +476,7 @@ struct TableMaker { } // Check whether we have to define barrel or muon histograms -<<<<<<< HEAD bool enableBarrelHistos = (context.mOptions.get("processPP") || context.mOptions.get("processPPWithFilter") || context.mOptions.get("processPPWithFilterBarrelOnly") || context.mOptions.get("processPPBarrelOnly") || -======= - bool enableBarrelHistos = (context.mOptions.get("processPPWithFilter") || context.mOptions.get("processPPWithFilterBarrelOnly") || context.mOptions.get("processPPBarrelOnly") || ->>>>>>> daa02bd72 (Qvector-tables shall be filled for all PbPb processes (except for processPbPbWithFilterBarrelOnly). Added a configurable for Qvector calibration path. The tables shall only be filled if the calibrations are available) context.mOptions.get("processPbPb") || context.mOptions.get("processPbPbBarrelOnly") || context.mOptions.get("processPbPbBarrelOnlyWithV0Bits") || context.mOptions.get("processPbPbBarrelOnlyWithV0BitsNoTOF")) || context.mOptions.get("processPbPbWithFilterBarrelOnly") || context.mOptions.get("processPPBarrelOnlyWithV0s") || context.mOptions.get("processPbPbBarrelOnlyNoTOF"); @@ -1198,33 +1191,6 @@ struct TableMaker { qvecGroup.eventQvectorCentr(collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.qvecFT0CRe(), collision.qvecFT0CIm(), collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.qvecFV0ARe(), collision.qvecFV0AIm(), collision.qvecTPCposRe(), collision.qvecTPCposIm(), collision.qvecTPCnegRe(), collision.qvecTPCnegIm(), collision.sumAmplFT0A(), collision.sumAmplFT0C(), collision.sumAmplFT0M(), collision.sumAmplFV0A(), collision.nTrkTPCpos(), collision.nTrkTPCneg()); qvecGroup.eventQvectorCentrExtra(collision.qvecTPCallRe(), collision.qvecTPCallIm(), collision.nTrkTPCall()); - - if (fConfigQvector.fConfigFT0CCumulant) { - // FT0C cumulants for RefFlow and QvectorExtra - float S11C = collision.sumAmplFT0C(); - float S12C = 0.f; - if constexpr (!std::is_same_v, std::nullptr_t>) { - if (collision.has_foundFT0()) { - auto ft0 = collision.foundFT0(); - for (auto amp : ft0.amplitudeC()) { - if (amp > 0.f) { - S12C += amp * amp; - } - } - } - } - float S21C = S11C * S11C; - float M11REF = S21C - S12C; - std::complex Q21C(collision.qvecFT0CRe() * S11C, collision.qvecFT0CIm() * S11C); - float CORR2REF = (std::norm(Q21C) - S12C) / M11REF; - - if (std::isnan(M11REF) || std::isinf(M11REF) || std::isnan(CORR2REF) || std::isinf(CORR2REF)) { - M11REF = 0.f; - CORR2REF = 0.f; - } - qvecGroup.eventRefFlow(M11REF, -9999, -9999, CORR2REF, -9999, -9999, VarManager::fgValues[VarManager::kCentFT0C]); - qvecGroup.eventQvectorExtra(-9999, -9999, -9999, -9999, S11C, S12C, -9999, -9999); - } } } if constexpr ((TEventFillMap & VarManager::ObjTypes::Zdc) > 0) { diff --git a/PWGDQ/Tasks/dqFlow.cxx b/PWGDQ/Tasks/dqFlow.cxx index 7b2232dcaff..fe16c52daee 100644 --- a/PWGDQ/Tasks/dqFlow.cxx +++ b/PWGDQ/Tasks/dqFlow.cxx @@ -353,6 +353,53 @@ struct DQEventQvector { // } } + // Templated function instantianed for all of the process functions + template + void runFillQvectorFromCentralFWWithFT0CCumulants(TEvent const& collision, TFT0s const& /*ft0s*/) + { + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(collision); + + float S11C = collision.sumAmplFT0C(); + float S12C = 0.f; + float S21C = S11C * S11C; + + // Compute sum of squares of amplitudes from FT0C for flow analysis + if (collision.has_foundFT0()) { + auto ft0 = collision.foundFT0(); + auto const& ampC = ft0.amplitudeC(); + for (auto amp : ampC) { + if (amp > 0.f) { + S12C += amp * amp; + } + } + } + VarManager::FillQVectorFromCentralFW(collision); + std::complex Q21C(collision.qvecFT0CRe() * S11C, collision.qvecFT0CIm() * S11C); + + // Fill necessary quantities for cumulant calculations with weighted Q-vectors + float M11REF = S21C - S12C; + float CORR2REF = (norm(Q21C) - S12C) / M11REF; + CORR2REF = std::isnan(M11REF) || std::isinf(M11REF) || std::isnan(CORR2REF) || std::isinf(CORR2REF) ? 0 : CORR2REF; + M11REF = std::isnan(M11REF) || std::isinf(M11REF) || std::isnan(CORR2REF) || std::isinf(CORR2REF) ? 0 : M11REF; + + if (fConfigQA) { + fHistMan->FillHistClass("Event_BeforeCuts_centralFW", VarManager::fgValues); + if (fEventCut->IsSelected(VarManager::fgValues)) { + fHistMan->FillHistClass("Event_AfterCuts_centralFW", VarManager::fgValues); + } + } + + if (fEventCut->IsSelected(VarManager::fgValues)) { + // temporarily removed --> this table is filled in the table-maker directly + // eventQvectorCentr(collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.qvecFT0CRe(), collision.qvecFT0CIm(), collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.qvecFV0ARe(), collision.qvecFV0AIm(), collision.qvecTPCposRe(), collision.qvecTPCposIm(), collision.qvecTPCnegRe(), collision.qvecTPCnegIm(), + // collision.sumAmplFT0A(), collision.sumAmplFT0C(), collision.sumAmplFT0M(), collision.sumAmplFV0A(), collision.nTrkTPCpos(), collision.nTrkTPCneg()); + // eventQvectorCentrExtra(collision.qvecTPCallRe(), collision.qvecTPCallIm(), collision.nTrkTPCall()); + eventRefFlow(M11REF, -9999, -9999, CORR2REF, -9999, -9999, VarManager::fgValues[VarManager::kCentFT0C]); + eventQvectorExtra(-9999, -9999, -9999, -9999, S11C, S12C, -9999, -9999); + } + } + // Templated function instantianed for all of the process functions template void runFillQvector(TEvent const& collision, MyBcs const&, TTracks const& tracks1, aod::Zdcs const&) @@ -576,6 +623,12 @@ struct DQEventQvector { runFillQvectorFromCentralFW(collisions); } + // Process to fill Q vector using barrel tracks in a reduced event table for barrel/muon tracks flow related analyses Run 3 + void processCentralQvectorWithFT0CCumulants(MyEventsWithCentQvectRun3::iterator const& collision, aod::FT0s const& ft0s) + { + runFillQvectorFromCentralFWWithFT0CCumulants(collision, ft0s); + } + // Process to fill Q vector using forward tracks in a reduced event table for barrel/muon tracks flow related analyses Run 3 void processForwardQvector(MyEventsWithCentRun3::iterator const& collisions, MyBcs const& bcs, soa::Filtered const& tracks, aod::Zdcs const& zdcs) { @@ -592,6 +645,7 @@ struct DQEventQvector { PROCESS_SWITCH(DQEventQvector, processBarrelQvector, "Run q-vector task on barrel tracks for Run3", false); PROCESS_SWITCH(DQEventQvector, processAllQvector, "Run q-vector task on barrel tracks for Run3 and using central q-vector", false); PROCESS_SWITCH(DQEventQvector, processCentralQvector, "Run q-vector task using central q-vector", false); + PROCESS_SWITCH(DQEventQvector, processCentralQvectorWithFT0CCumulants, "Run q-vector task using central q-vector with FT0C cumulants", false); PROCESS_SWITCH(DQEventQvector, processForwardQvector, "Run q-vector task on forward tracks for Run3", false); PROCESS_SWITCH(DQEventQvector, processDummy, "Dummy function", false); };