From ea16cb6f1cb6095a0bbd818cf3e30fc1243e3454 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 190d7dc4391..a2159b32c2a 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -187,8 +187,6 @@ struct TableMaker { Produces eventExtended; Produces eventVtxCov; Produces eventInfo; - Produces eventQvectorCentr; - Produces eventQvectorCentrExtra; Produces zdc; Produces fit; Produces multPV; @@ -209,6 +207,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 @@ -289,6 +295,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"}; @@ -1179,9 +1191,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) { @@ -1937,6 +1976,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, @@ -2040,6 +2089,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 6cd07e930d4cd12f975c0c75db5dd440c0827d99 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 a2159b32c2a..f978969680e 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -295,10 +295,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 { @@ -1192,7 +1192,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) { @@ -1213,7 +1213,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; @@ -1978,8 +1978,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 b01deacf7d7bd071b67a8aa8b8d2b6eae8c682e9 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 f978969680e..502869823a0 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -295,10 +295,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 { @@ -336,6 +336,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 @@ -480,7 +481,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"); @@ -1191,38 +1196,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 @@ -1772,6 +1778,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); @@ -1957,43 +1986,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) @@ -2007,23 +2026,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 @@ -2089,7 +2108,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 d05cf5080ec90598ac694fd7b0d6fa41a1f0c840 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 502869823a0..d21021e9d6d 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -295,10 +295,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 { @@ -336,7 +336,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 @@ -1198,7 +1198,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) { @@ -1219,7 +1219,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; @@ -1778,7 +1778,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; @@ -1787,10 +1787,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 a78f525cae8dedca9711a1666b8f04009f7e5dae 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 d21021e9d6d..89df91fdebf 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -298,7 +298,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 { @@ -336,7 +336,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 @@ -1196,7 +1195,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()); @@ -1778,29 +1777,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 2b8585b82c4814e3a239a620e96a5385a2429c90 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 89df91fdebf..1ae278c9301 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -211,8 +211,6 @@ struct TableMaker { struct : ProducesGroup { Produces eventQvectorCentr; Produces eventQvectorCentrExtra; - Produces eventQvectorExtra; - Produces eventRefFlow; } qvecGroup; OutputObj fOutputList{"output"}; //! the histogram manager output list @@ -297,7 +295,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; @@ -480,11 +477,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"); @@ -1199,33 +1192,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); };