From 6628e6ad91b90ead912e0ff1107350f67d1b7c51 Mon Sep 17 00:00:00 2001 From: wenyaCern Date: Wed, 10 Sep 2025 17:59:25 +0200 Subject: [PATCH 1/3] Add functions for flow and qn in femto dream --- .../Core/femtoDreamCollisionSelection.h | 2 +- .../femtoDreamProducerReducedTask.cxx | 214 +++++++++++++++++- 2 files changed, 211 insertions(+), 5 deletions(-) diff --git a/PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h b/PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h index c8a3947b141..97823dad4f8 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h +++ b/PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h @@ -489,7 +489,7 @@ class FemtoDreamCollisionSelection } private: - HistogramRegistry* mHistogramRegistry = nullptr; ///< For QA output + HistogramRegistry* mHistogramRegistry = nullptr; ///< For QA output bool mCutsSet = false; ///< Protection against running without cuts bool mCheckTrigger = false; ///< Check for trigger bool mCheckOffline = false; ///< Check for offline criteria (might change) diff --git a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerReducedTask.cxx b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerReducedTask.cxx index dc5fcc8a862..cbd71cd1714 100644 --- a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerReducedTask.cxx +++ b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerReducedTask.cxx @@ -55,6 +55,7 @@ namespace o2::aod using FemtoFullCollision = soa::Join::iterator; using FemtoFullCollisionMC = soa::Join::iterator; using FemtoFullCollision_noCent_MC = soa::Join::iterator; +using FemtoFullCollision_CentPbPb = soa::Join::iterator; using FemtoFullTracks = soa::Join outputCollision; + Produces outputExtQnCollision; Produces outputParts; Produces outputPartsMC; Produces outputDebugParts; @@ -104,14 +106,39 @@ struct femtoDreamProducerReducedTask { Configurable> ConfTrkITSnclsIbMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kITSnClsIbMin, "ConfTrk"), std::vector{-1.f, 1.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kITSnClsIbMin, "Track selection: ")}; Configurable> ConfTrkDCAxyMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kDCAxyMax, "ConfTrk"), std::vector{0.1f, 0.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kDCAxyMax, "Track selection: ")}; /// here we need an open cut to do the DCA fits later on! Configurable> ConfTrkDCAzMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kDCAzMax, "ConfTrk"), std::vector{0.2f, 0.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kDCAzMax, "Track selection: ")}; - Configurable> ConfTrkPIDnSigmaMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kPIDnSigmaMax, "Conf"), std::vector{3.5f, 3.f, 2.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kPIDnSigmaMax, "Track selection: ")}; + Configurable> ConfTrkPIDnSigmaMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kPIDnSigmaMax, "ConfTrk"), std::vector{3.5f, 3.f, 2.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kPIDnSigmaMax, "Track selection: ")}; // off set the center of the nsigma distribution to deal with bad TPC/TOF calibration Configurable ConfTrkPIDnSigmaOffsetTPC{"ConfTrkPIDnSigmaOffsetTPC", 0., "Offset for TPC nSigma because of bad calibration"}; Configurable ConfTrkPIDnSigmaOffsetTOF{"ConfTrkPIDnSigmaOffsetTOF", 0., "Offset for TOF nSigma because of bad calibration"}; Configurable> ConfTrkPIDspecies{"ConfTrkPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Kaon, o2::track::PID::Proton, o2::track::PID::Deuteron}, "Trk sel: Particles species for PID"}; + struct : o2::framework::ConfigurableGroup { + Configurable ConfgFlowCalculate{"ConfgFlowCalculate", false, "Evt sel: Cumulant of flow"}; // To do + Configurable ConfgQnSeparation{"ConfgQnSeparation", false, "Evt sel: Qn of event"}; + Configurable> ConfQnBinSeparator{"ConfQnBinSeparator", std::vector{-999.f, -999.f, -999.f}, "Qn bin separator"}; + Configurable ConfCentralityMax{"ConfCentralityMax", 80.f, "Evt sel: Maximum Centrality cut"}; + Configurable ConfCentBinWidth{"ConfCentBinWidth", 1.f, "Centrality bin length for qn separator"}; + Configurable ConfQnBinMin{"ConfQnBinMin", 0, "Minimum qn bin"}; + Configurable ConfQnBinMax{"ConfQnBinMax", 10, "Maximum qn bin"}; + } qnCal; + + struct : o2::framework::ConfigurableGroup { + Configurable ConfIsPbPb{"ConfIsPbPb", false, "Running on Run3 or Run2"}; // Choose if running on PbPb data + Configurable ConfIsUsePileUp{"ConfIsUsePileUp", false, "Required for choosing whether to run the pile-up cuts"}; + Configurable ConfEvNoSameBunchPileup{"ConfEvNoSameBunchPileup", false, "Require kNoSameBunchPileup selection on Events."}; + Configurable ConfEvIsGoodZvtxFT0vsPV{"ConfEvIsGoodZvtxFT0vsPV", false, "Require kIsGoodZvtxFT0vsPV selection on Events."}; + Configurable ConfEvIsGoodITSLayersAll{"ConfEvIsGoodITSLayersAll", false, "Require kIsGoodITSLayersAll selection on Events."}; + Configurable ConfEvNoCollInRofStandard{"ConfEvNoCollInRofStandard", false, "Require kNoCollInRofStandard selection on Events."}; + Configurable ConfEvNoHighMultCollInPrevRof{"ConfEvNoHighMultCollInPrevRof", false, "Require kNoHighMultCollInPrevRof selection on Events."}; + Configurable ConfEvNoCollInTimeRangeStandard{"ConfEvNoCollInTimeRangeStandard", false, "Require kNoCollInTimeRangeStandard selection on Events."}; + Configurable ConfEvIsVertexITSTPC{"ConfEvIsVertexITSTPC", false, "Require kIsVertexITSTPC selection on Events"}; + Configurable ConfTPCOccupancyMin{"ConfTPCOccupancyMin", 0, "Minimum value for TPC Occupancy selection"}; + Configurable ConfTPCOccupancyMax{"ConfTPCOccupancyMax", 1000, "Maximum value for TPC Occupancy selection"}; + } evtSel_PbPb; + HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry Registry{"Tracks", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry FlowRegistry{"QnandFlowInfo", {}, OutputObjHandlingPolicy::AnalysisObject}; int mRunNumber; float mMagField; @@ -144,6 +171,11 @@ struct femtoDreamProducerReducedTask { trackCuts.init(&qaRegistry, &Registry); + + if (qnCal.ConfgFlowCalculate){ + colCuts.initFlow(&FlowRegistry, qnCal.ConfgQnSeparation); + } + mRunNumber = 0; mMagField = 0.0; /// Initializing CCDB @@ -330,8 +362,166 @@ struct femtoDreamProducerReducedTask { } } - void - processData(aod::FemtoFullCollision const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks) + // Centrality (Multiplicity percentile) obtained from FT0C + // Pile-up rejection involved + template + void fillCollisionsAndTracks_PbPb(CollisionType const& col, TrackType const& tracks) + { + const auto vtxZ = col.posZ(); + const auto spher = colCuts.computeSphericity(col, tracks); + int mult = 0; + int multNtr = 0; + if (ConfIsRun3) { + if constexpr (useCentrality) { + mult = col.centFT0C(); + } else { + mult = 0.; + } + multNtr = col.multNTracksPV(); + } else { + mult = 1; // multiplicity percentile is known in Run 2 + multNtr = col.multTracklets(); + } + if (ConfEvtUseTPCmult) { + multNtr = col.multTPC(); + } + colCuts.fillQA(col, mult); + + /// First thing to do is to check whether the basic event selection criteria are fulfilled + /// That includes checking if there are any usable tracks in a collision + if (!colCuts.isSelectedCollision(col)) { + return; + } + if (colCuts.isEmptyCollision(col, tracks, trackCuts)) { + return; + } + + // Pileup rejection in PbPb data + if (evtSel_PbPb.ConfIsPbPb && evtSel_PbPb.ConfIsUsePileUp && + !colCuts.isPileUpCollisionPbPb(col, evtSel_PbPb.ConfEvNoSameBunchPileup, evtSel_PbPb.ConfEvIsGoodZvtxFT0vsPV, + evtSel_PbPb.ConfEvIsGoodITSLayersAll, evtSel_PbPb.ConfEvNoCollInRofStandard, + evtSel_PbPb.ConfEvNoHighMultCollInPrevRof, evtSel_PbPb.ConfEvNoCollInTimeRangeStandard, + evtSel_PbPb.ConfEvIsVertexITSTPC, + evtSel_PbPb.ConfTPCOccupancyMin, evtSel_PbPb.ConfTPCOccupancyMax)) { + return; + } + // now the table is filled + outputCollision(vtxZ, mult, multNtr, spher, mMagField); + + // these IDs are necessary to keep track of the children + // since this producer only produces the tables for tracks, there are no children + std::vector childIDs = {0, 0}; + for (auto& track : tracks) { + /// if the most open selection criteria are not fulfilled there is no point looking further at the track + if (!trackCuts.isSelectedMinimal(track)) { + continue; + } + trackCuts.fillQA(track); + // an array of two bit-wise containers of the systematic variations is obtained + // one container for the track quality cuts and one for the PID cuts + auto cutContainer = trackCuts.getCutContainer(track, track.pt(), track.eta(), sqrtf(powf(track.dcaXY(), 2.f) + powf(track.dcaZ(), 2.f))); + + // now the table is filled + outputParts(outputCollision.lastIndex(), + track.pt(), + track.eta(), + track.phi(), + aod::femtodreamparticle::ParticleType::kTrack, + cutContainer.at(femtoDreamTrackSelection::TrackContainerPosition::kCuts), + cutContainer.at(femtoDreamTrackSelection::TrackContainerPosition::kPID), + track.dcaXY(), childIDs, 0, 0); + if constexpr (isMC) { + fillMCParticle(col, track, o2::aod::femtodreamparticle::ParticleType::kTrack); + } + + if (ConfIsDebug) { + outputDebugParts(track.sign(), + (uint8_t)track.tpcNClsFound(), + track.tpcNClsFindable(), + (uint8_t)track.tpcNClsCrossedRows(), + track.tpcNClsShared(), + track.tpcInnerParam(), + track.itsNCls(), + track.itsNClsInnerBarrel(), + track.dcaXY(), + track.dcaZ(), + track.tpcSignal(), + track.tpcNSigmaEl(), + track.tpcNSigmaPi(), + track.tpcNSigmaKa(), + track.tpcNSigmaPr(), + track.tpcNSigmaDe(), + track.tpcNSigmaTr(), + track.tpcNSigmaHe(), + track.tofNSigmaEl(), + track.tofNSigmaPi(), + track.tofNSigmaKa(), + track.tofNSigmaPr(), + track.tofNSigmaDe(), + track.tofNSigmaTr(), + track.tofNSigmaHe(), + -1, + track.itsNSigmaEl(), + track.itsNSigmaPi(), + track.itsNSigmaKa(), + track.itsNSigmaPr(), + track.itsNSigmaDe(), + track.itsNSigmaTr(), + track.itsNSigmaHe(), + -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999.); + } + } + } + + // Calculate and separate qn bins + // Do and fill cumulant in qn bins + template + void fillCollisionsFlow(CollisionType const& col, TrackType const& tracks) + { + // get magnetic field for run + + const auto spher = colCuts.computeSphericity(col, tracks); + int multNtr = 0; + if (ConfIsRun3) { + multNtr = col.multNTracksPV(); + } else { + multNtr = col.multTracklets(); + } + if (ConfEvtUseTPCmult) { + multNtr = col.multTPC(); + } + + /// First thing to do is to check whether the basic event selection criteria are fulfilled + /// That includes checking if there are any usable tracks in a collision + if (!colCuts.isSelectedCollision(col)) { + return; + } + if (colCuts.isEmptyCollision(col, tracks, trackCuts)) { + return; + } + + // Pileup rejection in PbPb data + if (evtSel_PbPb.ConfIsPbPb && evtSel_PbPb.ConfIsUsePileUp && + !colCuts.isPileUpCollisionPbPb(col, evtSel_PbPb.ConfEvNoSameBunchPileup, evtSel_PbPb.ConfEvIsGoodZvtxFT0vsPV, + evtSel_PbPb.ConfEvIsGoodITSLayersAll, evtSel_PbPb.ConfEvNoCollInRofStandard, + evtSel_PbPb.ConfEvNoHighMultCollInPrevRof, evtSel_PbPb.ConfEvNoCollInTimeRangeStandard, + evtSel_PbPb.ConfEvIsVertexITSTPC, + evtSel_PbPb.ConfTPCOccupancyMin, evtSel_PbPb.ConfTPCOccupancyMax)) { + return; + } + + // Calculate and fill qnBins + auto qnBin = colCuts.myqnBin(col, qnCal.ConfCentralityMax, qnCal.ConfQnBinSeparator, spher, multNtr, 1.f); + if (qnBin < qnCal.ConfQnBinMin || qnBin > qnCal.ConfQnBinMax){ + qnBin = -999; + } + colCuts.fillCumulants(col, tracks); + colCuts.doCumulants(col, qnCal.ConfgQnSeparation, qnBin); + outputExtQnCollision(qnBin); + } + + void processData(aod::FemtoFullCollision const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks) { // get magnetic field for run getMagneticFieldTesla(col.bc_as()); @@ -370,8 +560,24 @@ struct femtoDreamProducerReducedTask { fillCollisionsAndTracks(col, tracksWithItsPid); } PROCESS_SWITCH(femtoDreamProducerReducedTask, processMC_noCentrality, "Provide MC data", false); + + void processData_FlowCalc(aod::FemtoFullCollision_CentPbPb const& col, + aod::BCsWithTimestamps const&, + aod::FemtoFullTracks const& tracks) + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + auto tracksWithItsPid = soa::Attach(tracks); + // fill the tables + fillCollisionsAndTracks_PbPb(col, tracksWithItsPid); + if (qnCal.ConfgQnSeparation){ + fillCollisionsFlow(col, tracksWithItsPid); + } + } + PROCESS_SWITCH(femtoDreamProducerReducedTask, processData_FlowCalc, + "Provide experimental data with cumulant flow calculation", false); }; - WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; From 75a19daf630cd3beca1103c12f1e67c7a9bd6a35 Mon Sep 17 00:00:00 2001 From: mutecho <65065864+mutecho@users.noreply.github.com> Date: Fri, 14 Nov 2025 14:24:06 +0800 Subject: [PATCH 2/3] modified according to suggestion --- .gitignore | 2 +- PWGCF/FemtoDream/Core/femtoDreamContainer.h | 135 ++++++++++++++++++-- 2 files changed, 128 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 73ebcda4683..b124370a288 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,4 @@ github_conf/ xcuserdata/ #QtCreator -CMakeLists.txt.user +CMakeLists.txt.user \ No newline at end of file diff --git a/PWGCF/FemtoDream/Core/femtoDreamContainer.h b/PWGCF/FemtoDream/Core/femtoDreamContainer.h index 2b58f0e9c5c..18363a75ceb 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamContainer.h +++ b/PWGCF/FemtoDream/Core/femtoDreamContainer.h @@ -332,7 +332,7 @@ class FemtoDreamContainer } const float mTMC = FemtoDreamMath::getmT(part1.fdMCParticle(), mMassOne, part2, mMassTwo); - if (abs(part1.fdMCParticle().pdgMCTruth()) == mPDGOne) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates + if (std::abs(part1.fdMCParticle().pdgMCTruth()) == mPDGOne) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates setPair_base(femtoObsMC, mTMC, part1.fdMCParticle(), part2, mult, multPercentile, use4dplots, extendedplots); setPair_MC(femtoObsMC, femtoObs, mT, mult, part1.fdMCParticle().partOriginMCTruth(), part2.flagMc(), smearingByOrigin); } else { @@ -346,7 +346,7 @@ class FemtoDreamContainer } const float mTMC = FemtoDreamMath::getmT(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); - if (abs(part1.fdMCParticle().pdgMCTruth()) == mPDGOne && abs(part2.fdMCParticle().pdgMCTruth()) == mPDGTwo) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates + if (std::abs(part1.fdMCParticle().pdgMCTruth()) == mPDGOne && std::abs(part2.fdMCParticle().pdgMCTruth()) == mPDGTwo) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates setPair_base(femtoObsMC, mTMC, part1.fdMCParticle(), part2.fdMCParticle(), mult, multPercentile, use4dplots, extendedplots); setPair_MC(femtoObsMC, femtoObs, mT, mult, part1.fdMCParticle().partOriginMCTruth(), part2.fdMCParticle().partOriginMCTruth(), smearingByOrigin); } else { @@ -364,13 +364,53 @@ class FemtoDreamContainer template void setPair_qn_base(const float femtoObs, const float mT, const float multPercentile, const int myQnBin, const int numQnBins = 10) { - if (myQnBin >= 0 && myQnBin < numQnBins) { - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("_qn") + HIST("/relPairkstarmTMultMultPercentileQn"), femtoObs, mT, multPercentile, myQnBin); - } else { - return; + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("_EP") + HIST("/relPairkstarmTMultMultPercentileQn"), femtoObs, mT, multPercentile, myEPObs); + } + + template + void setPair_EP(T1 const& part1, T2 const& part2, const float multPercentile, const bool doQnSeparation, float myEPObs) + { + float femtoObs, femtoObsMC; + // Calculate femto observable and the mT with reconstructed information + if constexpr (mFemtoObs == femtoDreamContainer::Observable::kstar) { + femtoObs = FemtoDreamMath::getkstar(part1, mMassOne, part2, mMassTwo); + } + if (mHighkstarCut > 0) { + if (femtoObs > mHighkstarCut) { + return; + } + } + const float mT = FemtoDreamMath::getmT(part1, mMassOne, part2, mMassTwo); + + if (!doQnSeparation) { + myEPObs = FemtoDreamMath::getPairPhiEP(part1, mMassOne, part2, mMassTwo, myEPObs); + } + + if (mHistogramRegistry) { + setPair_EP_base(femtoObs, mT, multPercentile, myEPObs); + + if constexpr (isMC) { + if (part1.has_fdMCParticle() && part2.has_fdMCParticle()) { + // calculate the femto observable and the mT with MC truth information + if constexpr (mFemtoObs == femtoDreamContainer::Observable::kstar) { + femtoObsMC = FemtoDreamMath::getkstar(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); + } + const float mTMC = FemtoDreamMath::getmT(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); + + if (std::abs(part1.fdMCParticle().pdgMCTruth()) == mPDGOne && std::abs(part2.fdMCParticle().pdgMCTruth()) == mPDGTwo) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates + setPair_EP_base(femtoObsMC, mTMC, multPercentile, myEPObs); + } else { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/hFakePairsCounter"), 0); + } + + } else { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/hNoMCtruthPairsCounter"), 0); + } + } } } + // while doing mixing for EP, we have to compute the phi angular of a pair according to plane-calibarated second particle template void setPair_qn(T1 const& part1, T2 const& part2, const float multPercentile, const int myQnBin, const int numQnBins = 10) { @@ -397,8 +437,87 @@ class FemtoDreamContainer } const float mTMC = FemtoDreamMath::getmT(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); - if (abs(part1.fdMCParticle().pdgMCTruth()) == mPDGOne && abs(part2.fdMCParticle().pdgMCTruth()) == mPDGTwo) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates - setPair_qn_base(femtoObsMC, mTMC, multPercentile, myQnBin, numQnBins); + if (std::abs(part1.fdMCParticle().pdgMCTruth()) == mPDGOne && std::abs(part2.fdMCParticle().pdgMCTruth()) == mPDGTwo) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates + setPair_EP_base(femtoObsMC, mTMC, multPercentile, EP1); + } else { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/hFakePairsCounter"), 0); + } + + } else { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/hNoMCtruthPairsCounter"), 0); + } + } + } + } + + /// Pass a pair to the container and compute all the relevant observables in divided qn bins + template + void setPair_3Dqn_base(const float femtoDKout, const float femtoDKside, const float femtoDKlong, const float mT, const float multPercentile, const float myQnBin, const float pairPhiEP) + { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("_3Dqn") + HIST("/relPair3dRmTMultPercentileQnPairphi"), femtoDKout, femtoDKside, femtoDKlong, mT, multPercentile, myQnBin, pairPhiEP); + } + + template + void setPair_3Dqn(T1 const& part1, T2 const& part2, const float multPercentile, bool IsSameSpecies, const float myQnBin, const float eventPlane) + { + + std::vector k3d = FemtoDreamMath::newpairfunc(part1, mMassOne, part2, mMassTwo, IsSameSpecies); + float DKout = k3d[1]; + float DKside = k3d[2]; + float DKlong = k3d[3]; + + const float mT = FemtoDreamMath::getmT(part1, mMassOne, part2, mMassTwo); + + const float pairPhiEP = FemtoDreamMath::getPairPhiEP(part1, mMassOne, part2, mMassTwo, eventPlane); + + if (mHistogramRegistry) { + setPair_3Dqn_base(DKout, DKside, DKlong, mT, multPercentile, myQnBin, pairPhiEP); + + if constexpr (isMC) { + if (part1.has_fdMCParticle() && part2.has_fdMCParticle()) { + + std::vector k3dMC = FemtoDreamMath::newpairfunc(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo, IsSameSpecies); + const float mTMC = FemtoDreamMath::getmT(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); + const float pairPhiEPMC = FemtoDreamMath::getPairPhiEP(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo, eventPlane); + + if (std::abs(part1.fdMCParticle().pdgMCTruth()) == mPDGOne && std::abs(part2.fdMCParticle().pdgMCTruth()) == mPDGTwo) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates + setPair_3Dqn_base(k3dMC[1], k3dMC[2], k3dMC[3], mTMC, multPercentile, myQnBin, pairPhiEPMC); + } else { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/hFakePairsCounter"), 0); + } + + } else { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/hNoMCtruthPairsCounter"), 0); + } + } + } + } + + template + void setPair_3Dqn(T1 const& part1, T2 const& part2, const float multPercentile, bool IsSameSpecies, const float myQnBin, const float EP1, const float EP2) + { + + std::vector k3d = FemtoDreamMath::newpairfunc(part1, mMassOne, part2, mMassTwo, IsSameSpecies); + float DKout = k3d[1]; + float DKside = k3d[2]; + float DKlong = k3d[3]; + + const float mT = FemtoDreamMath::getmT(part1, mMassOne, part2, mMassTwo); + + const float pairPhiEP = FemtoDreamMath::getPairPhiEP(part1, mMassOne, part2, mMassTwo, EP1, EP2); + + if (mHistogramRegistry) { + setPair_3Dqn_base(DKout, DKside, DKlong, mT, multPercentile, myQnBin, pairPhiEP); + + if constexpr (isMC) { + if (part1.has_fdMCParticle() && part2.has_fdMCParticle()) { + + std::vector k3dMC = FemtoDreamMath::newpairfunc(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo, IsSameSpecies); + const float mTMC = FemtoDreamMath::getmT(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); + const float pairPhiEPMC = FemtoDreamMath::getPairPhiEP(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo, EP1, EP2); + + if (std::abs(part1.fdMCParticle().pdgMCTruth()) == mPDGOne && std::abs(part2.fdMCParticle().pdgMCTruth()) == mPDGTwo) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates + setPair_3Dqn_base(k3dMC[1], k3dMC[2], k3dMC[3], mTMC, multPercentile, myQnBin, pairPhiEPMC); } else { mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/hFakePairsCounter"), 0); } From c347de17b202629941919044b8c92c3b77afa673 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Fri, 14 Nov 2025 07:41:09 +0000 Subject: [PATCH 3/3] Please consider the following formatting changes --- .../Core/femtoDreamCollisionSelection.h | 2 +- .../femtoDreamProducerReducedTask.cxx | 46 +++++++++---------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h b/PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h index 816e18ca57d..4e67c43b40c 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h +++ b/PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h @@ -504,7 +504,7 @@ class FemtoDreamCollisionSelection } private: - HistogramRegistry* mHistogramRegistry = nullptr; ///< For QA output + HistogramRegistry* mHistogramRegistry = nullptr; ///< For QA output bool mCutsSet = false; ///< Protection against running without cuts bool mCheckTrigger = false; ///< Check for trigger bool mCheckOffline = false; ///< Check for offline criteria (might change) diff --git a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerReducedTask.cxx b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerReducedTask.cxx index cbd71cd1714..819ca1b4ca6 100644 --- a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerReducedTask.cxx +++ b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerReducedTask.cxx @@ -115,8 +115,8 @@ struct femtoDreamProducerReducedTask { struct : o2::framework::ConfigurableGroup { Configurable ConfgFlowCalculate{"ConfgFlowCalculate", false, "Evt sel: Cumulant of flow"}; // To do Configurable ConfgQnSeparation{"ConfgQnSeparation", false, "Evt sel: Qn of event"}; - Configurable> ConfQnBinSeparator{"ConfQnBinSeparator", std::vector{-999.f, -999.f, -999.f}, "Qn bin separator"}; - Configurable ConfCentralityMax{"ConfCentralityMax", 80.f, "Evt sel: Maximum Centrality cut"}; + Configurable> ConfQnBinSeparator{"ConfQnBinSeparator", std::vector{-999.f, -999.f, -999.f}, "Qn bin separator"}; + Configurable ConfCentralityMax{"ConfCentralityMax", 80.f, "Evt sel: Maximum Centrality cut"}; Configurable ConfCentBinWidth{"ConfCentBinWidth", 1.f, "Centrality bin length for qn separator"}; Configurable ConfQnBinMin{"ConfQnBinMin", 0, "Minimum qn bin"}; Configurable ConfQnBinMax{"ConfQnBinMax", 10, "Maximum qn bin"}; @@ -171,8 +171,8 @@ struct femtoDreamProducerReducedTask { trackCuts.init(&qaRegistry, &Registry); - - if (qnCal.ConfgFlowCalculate){ + + if (qnCal.ConfgFlowCalculate) { colCuts.initFlow(&FlowRegistry, qnCal.ConfgQnSeparation); } @@ -397,12 +397,12 @@ struct femtoDreamProducerReducedTask { } // Pileup rejection in PbPb data - if (evtSel_PbPb.ConfIsPbPb && evtSel_PbPb.ConfIsUsePileUp && - !colCuts.isPileUpCollisionPbPb(col, evtSel_PbPb.ConfEvNoSameBunchPileup, evtSel_PbPb.ConfEvIsGoodZvtxFT0vsPV, - evtSel_PbPb.ConfEvIsGoodITSLayersAll, evtSel_PbPb.ConfEvNoCollInRofStandard, - evtSel_PbPb.ConfEvNoHighMultCollInPrevRof, evtSel_PbPb.ConfEvNoCollInTimeRangeStandard, - evtSel_PbPb.ConfEvIsVertexITSTPC, - evtSel_PbPb.ConfTPCOccupancyMin, evtSel_PbPb.ConfTPCOccupancyMax)) { + if (evtSel_PbPb.ConfIsPbPb && evtSel_PbPb.ConfIsUsePileUp && + !colCuts.isPileUpCollisionPbPb(col, evtSel_PbPb.ConfEvNoSameBunchPileup, evtSel_PbPb.ConfEvIsGoodZvtxFT0vsPV, + evtSel_PbPb.ConfEvIsGoodITSLayersAll, evtSel_PbPb.ConfEvNoCollInRofStandard, + evtSel_PbPb.ConfEvNoHighMultCollInPrevRof, evtSel_PbPb.ConfEvNoCollInTimeRangeStandard, + evtSel_PbPb.ConfEvIsVertexITSTPC, + evtSel_PbPb.ConfTPCOccupancyMin, evtSel_PbPb.ConfTPCOccupancyMax)) { return; } // now the table is filled @@ -475,7 +475,7 @@ struct femtoDreamProducerReducedTask { } // Calculate and separate qn bins - // Do and fill cumulant in qn bins + // Do and fill cumulant in qn bins template void fillCollisionsFlow(CollisionType const& col, TrackType const& tracks) { @@ -502,23 +502,23 @@ struct femtoDreamProducerReducedTask { } // Pileup rejection in PbPb data - if (evtSel_PbPb.ConfIsPbPb && evtSel_PbPb.ConfIsUsePileUp && - !colCuts.isPileUpCollisionPbPb(col, evtSel_PbPb.ConfEvNoSameBunchPileup, evtSel_PbPb.ConfEvIsGoodZvtxFT0vsPV, - evtSel_PbPb.ConfEvIsGoodITSLayersAll, evtSel_PbPb.ConfEvNoCollInRofStandard, - evtSel_PbPb.ConfEvNoHighMultCollInPrevRof, evtSel_PbPb.ConfEvNoCollInTimeRangeStandard, - evtSel_PbPb.ConfEvIsVertexITSTPC, - evtSel_PbPb.ConfTPCOccupancyMin, evtSel_PbPb.ConfTPCOccupancyMax)) { + if (evtSel_PbPb.ConfIsPbPb && evtSel_PbPb.ConfIsUsePileUp && + !colCuts.isPileUpCollisionPbPb(col, evtSel_PbPb.ConfEvNoSameBunchPileup, evtSel_PbPb.ConfEvIsGoodZvtxFT0vsPV, + evtSel_PbPb.ConfEvIsGoodITSLayersAll, evtSel_PbPb.ConfEvNoCollInRofStandard, + evtSel_PbPb.ConfEvNoHighMultCollInPrevRof, evtSel_PbPb.ConfEvNoCollInTimeRangeStandard, + evtSel_PbPb.ConfEvIsVertexITSTPC, + evtSel_PbPb.ConfTPCOccupancyMin, evtSel_PbPb.ConfTPCOccupancyMax)) { return; } - // Calculate and fill qnBins + // Calculate and fill qnBins auto qnBin = colCuts.myqnBin(col, qnCal.ConfCentralityMax, qnCal.ConfQnBinSeparator, spher, multNtr, 1.f); - if (qnBin < qnCal.ConfQnBinMin || qnBin > qnCal.ConfQnBinMax){ + if (qnBin < qnCal.ConfQnBinMin || qnBin > qnCal.ConfQnBinMax) { qnBin = -999; } colCuts.fillCumulants(col, tracks); colCuts.doCumulants(col, qnCal.ConfgQnSeparation, qnBin); - outputExtQnCollision(qnBin); + outputExtQnCollision(qnBin); } void processData(aod::FemtoFullCollision const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks) @@ -560,7 +560,7 @@ struct femtoDreamProducerReducedTask { fillCollisionsAndTracks(col, tracksWithItsPid); } PROCESS_SWITCH(femtoDreamProducerReducedTask, processMC_noCentrality, "Provide MC data", false); - + void processData_FlowCalc(aod::FemtoFullCollision_CentPbPb const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks) @@ -569,9 +569,9 @@ struct femtoDreamProducerReducedTask { getMagneticFieldTesla(col.bc_as()); auto tracksWithItsPid = soa::Attach(tracks); - // fill the tables + // fill the tables fillCollisionsAndTracks_PbPb(col, tracksWithItsPid); - if (qnCal.ConfgQnSeparation){ + if (qnCal.ConfgQnSeparation) { fillCollisionsFlow(col, tracksWithItsPid); } }