diff --git a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx index a857be78aa8..2c00522c77e 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)"}; + Configurable fConfigQvectCalibAvailable{"cfgQvectCalibAvailable", false, "If true, qvector calibration objects are available in CCDB for this run"}; + } fConfigQvector; + struct : ConfigurableGroup { // Track related options Configurable fPropTrack{"cfgPropTrack", true, "Propagate tracks to associated collision to recalculate DCA and momentum vector"}; @@ -1178,11 +1190,39 @@ 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(), - collision.sumAmplFT0A(), collision.sumAmplFT0C(), collision.sumAmplFT0M(), collision.sumAmplFV0A(), collision.nTrkTPCpos(), collision.nTrkTPCneg()); - eventQvectorCentrExtra(collision.qvecTPCallRe(), collision.qvecTPCallIm(), collision.nTrkTPCall()); + 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()); + + 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) { if constexpr ((TEventFillMap & VarManager::ObjTypes::RapidityGapFilter) > 0) { // The DQRapidityGapFilter contains the index of the bc we want to get ZDC info from @@ -1907,33 +1947,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); + 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) @@ -1947,23 +1987,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