diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx index 25719f7f8f5..fcc5cfa15a9 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx @@ -16,49 +16,52 @@ /// \since October 28, 2025 #include "PWGCF/Core/CorrelationContainer.h" -#include "PWGCF/Core/PairCuts.h" #include "PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGMM/Mult/DataModel/bestCollisionTable.h" +#include "PWGUD/Core/SGCutParHolder.h" #include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/Core/UPCHelpers.h" +#include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" -#include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.h" -#include "CommonConstants/MathConstants.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DetectorsCommonDataFormats/AlignParam.h" -#include "FT0Base/Geometry.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/PID.h" -#include "ReconstructionDataFormats/Track.h" - -#include -#include -#include -#include - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include #include +#include +#include #include +#include #include #include @@ -74,6 +77,8 @@ auto static constexpr CintZero = 0; auto static constexpr KminFt0cCell = 96; AxisSpec axisEvent{15, 0.5, 15.5, "#Event", "EventAxis"}; auto static constexpr KminCharge = 3.0f; +static constexpr std::string_view species[] = {"Pi", "Ka", "Pr", "K0s", "L0s"}; +static constexpr std::array speciesIds{kPiPlus, kKPlus, kProton, kK0Short, kLambda0}; enum KindOfV0 { kLambda = 0, @@ -105,6 +110,7 @@ struct LongrangeMaker { Configurable isApplyCentFT0M{"isApplyCentFT0M", false, "Centrality based on FT0A + FT0C"}; Configurable isApplyOccuSelection{"isApplyOccuSelection", false, "Enable occupancy selection"}; Configurable cfgOccuCut{"cfgOccuCut", 1000, "Occupancy selection"}; + Configurable cfgVtxCut{"cfgVtxCut", 10.0f, "vertex Z selection"}; Configurable isApplyBestCollIndex{"isApplyBestCollIndex", true, "bestCollIndex"}; } cfgevtsel; @@ -130,6 +136,13 @@ struct LongrangeMaker { Configurable cfgMftPtCutMax{"cfgMftPtCutMax", 10.f, "maximum accepted MFT track pT"}; } cfgmfttrksel; + struct : ConfigurableGroup { + Configurable cfigFt0aEtaMax{"cfigFt0aEtaMax", 4.9f, "Maximum FT0A eta cut"}; + Configurable cfigFt0aEtaMin{"cfigFt0aEtaMin", 3.5f, "Minimum FT0A eta cut"}; + Configurable cfigFt0cEtaMax{"cfigFt0cEtaMax", -2.1f, "Maximum FT0C eta cut"}; + Configurable cfigFt0cEtaMin{"cfigFt0cEtaMin", -3.3f, "Minimum FT0C eta cut"}; + } cfgfittrksel; + struct : ConfigurableGroup { Configurable minTPCcrossedrows{"minTPCcrossedrows", 70.f, "cut on minimum number of crossed rows in TPC"}; Configurable minTPCcrossedrowsoverfindcls{"minTPCcrossedrowsoverfindcls", 0.8f, "cut on minimum value of the ratio between crossed rows and findable clusters in the TPC"}; @@ -162,6 +175,13 @@ struct LongrangeMaker { Configurable> tofNsigmaPidCut{"tofNsigmaPidCut", std::vector{1.5, 1.5, 1.5, -1.5, -1.5, -1.5}, "TOF n-sigma cut for pions_posNsigma, kaons_posNsigma, protons_posNsigma, pions_negNsigma, kaons_negNsigma, protons_negNsigma"}; Configurable cfgTofPidPtCut{"cfgTofPidPtCut", 0.3f, "Minimum pt to use TOF N-sigma"}; Configurable isUseItsPid{"isUseItsPid", false, "Use ITS PID for particle identification"}; + Configurable isUseDataLikeMult{"isUseDataLikeMult", 0, "Data like mult/cent classification"}; + + ConfigurableAxis vtxHistBin{"vtxHistBin", {20, -10, 10}, ""}; + ConfigurableAxis multHistBin{"multHistBin", {100, 0, 100}, ""}; + ConfigurableAxis etaHistBin{"etaHistBin", {20, -1, 1}, ""}; + ConfigurableAxis ptHistBin{"ptHistBin", {10, 0, 10}, ""}; + ConfigurableAxis speciesHistBin{"speciesHistBin", {6, 0.5, 6.5}, ""}; Service ccdb; Service pdg; @@ -212,6 +232,27 @@ struct LongrangeMaker { x->SetBinLabel(12, "ApplyOccupancySelection"); histos.add("hSelectionResult", "hSelectionResult", kTH1I, {{5, -0.5, 4.5}}); + AxisSpec axisVtx = {vtxHistBin, "Vertex", "VtxAxis"}; + AxisSpec axisMult = {multHistBin, "Mult", "MultAxis"}; + AxisSpec axisEta = {etaHistBin, "Eta", "EtaAxis"}; + AxisSpec axisPt = {ptHistBin, "Pt", "PtAxis"}; + AxisSpec axisSpecies = {speciesHistBin, "Species", "SpeciesAxis"}; + + if (doprocessTPCtrackEff || doprocessMFTtrackEff) { + histos.add("hGenMCdndpt", "hGenMCdndpt", kTHnSparseD, {axisVtx, axisMult, axisEta, axisPt, axisSpecies}, false); + histos.add("hRecMCdndpt", "hRecMCdndpt", kTHnSparseD, {axisVtx, axisMult, axisEta, axisPt, axisSpecies}, false); + auto hGenSpecies = histos.get(HIST("hGenMCdndpt")); + auto hRecSpecies = histos.get(HIST("hRecMCdndpt")); + auto* axisGen = hGenSpecies->GetAxis(4); + auto* axisRec = hRecSpecies->GetAxis(4); + for (auto i = 0U; i < speciesIds.size(); ++i) { + axisGen->SetBinLabel(i + 1, species[i].data()); + axisRec->SetBinLabel(i + 1, species[i].data()); + } + axisGen->SetBinLabel(6, "Other"); + axisRec->SetBinLabel(6, "Other"); + } + myTrackFilter = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, TrackSelection::GlobalTrackRun3DCAxyCut::Default); myTrackFilter.SetPtRange(cfgtrksel.cfgPtCutMin, cfgtrksel.cfgPtCutMax); myTrackFilter.SetEtaRange(-cfgtrksel.cfgEtaCut, cfgtrksel.cfgEtaCut); @@ -604,12 +645,12 @@ struct LongrangeMaker { if (std::abs(particle.eta()) < cfgtrksel.cfgEtaCut && particle.pt() > cfgtrksel.cfgPtCutMin && particle.pt() < cfgtrksel.cfgPtCutMult) lrmidmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), particle.flags()); // Fill FT0 tracks - if (3.5 < particle.eta() && particle.eta() < 4.9) + if (cfgfittrksel.cfigFt0aEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfigFt0aEtaMax) lrft0amctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi()); - if (-3.3 < particle.eta() && particle.eta() < -2.1) + if (cfgfittrksel.cfigFt0cEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfigFt0cEtaMax) lrft0cmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi()); // Fill MFT tracks - if (-3.6 < particle.eta() && particle.eta() < -2.4) + if (cfgmfttrksel.cfigMftEtaMin < particle.eta() && particle.eta() < cfgmfttrksel.cfigMftEtaMax) lrmftmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi()); } } @@ -633,16 +674,137 @@ struct LongrangeMaker { if (std::abs(particle.eta()) < cfgtrksel.cfgEtaCut && particle.pt() > cfgtrksel.cfgPtCutMin && particle.pt() < cfgtrksel.cfgPtCutMult) lrmidmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), particle.flags()); // Fill FT0 tracks - if (3.5 < particle.eta() && particle.eta() < 4.9) + if (cfgfittrksel.cfigFt0aEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfigFt0aEtaMax) lrft0amctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi()); - if (-3.3 < particle.eta() && particle.eta() < -2.1) + if (cfgfittrksel.cfigFt0cEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfigFt0cEtaMax) lrft0cmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi()); // Fill MFT tracks - if (-3.6 < particle.eta() && particle.eta() < -2.4) + if (cfgmfttrksel.cfigMftEtaMin < particle.eta() && particle.eta() < cfgmfttrksel.cfigMftEtaMax) lrmftmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi()); } } + void processTPCtrackEff(ColMCTrueTable::iterator const& mcCollision, ColMCRecTable const& RecCols, + TrksMCRecTable const& RecTracks, aod::McParticles const& mcparticles) + { + if (std::abs(mcCollision.posZ()) >= cfgevtsel.cfgVtxCut) { + return; + } + auto multiplicity = 0; + for (const auto& particle : mcparticles) { + if (!isGenPartSelected(particle) || std::abs(particle.eta()) > cfgtrksel.cfgEtaCut || particle.pt() < cfgtrksel.cfgPtCutMin || particle.pt() > cfgtrksel.cfgPtCutMult) + continue; + multiplicity++; + } + if (isUseDataLikeMult > 0) { + for (const auto& RecCol : RecCols) { + if (!isEventSelected(RecCol)) { + continue; + } + if (std::abs(RecCol.posZ()) >= cfgevtsel.cfgVtxCut) { + continue; + } + if (cfgevtsel.isApplyBestCollIndex && RecCol.globalIndex() != mcCollision.bestCollisionIndex()) { + continue; + } + multiplicity = selColCent(RecCol); + } + } + + for (const auto& particle : mcparticles) { + if (!isGenPartSelected(particle) || std::abs(particle.eta()) > cfgtrksel.cfgEtaCut || particle.pt() < cfgtrksel.cfgPtCutMin || particle.pt() > cfgtrksel.cfgPtCutMult) + continue; + auto pos = std::distance(speciesIds.begin(), std::find(speciesIds.begin(), speciesIds.end(), particle.pdgCode())) + 1; + histos.fill(HIST("hGenMCdndpt"), mcCollision.posZ(), multiplicity, particle.eta(), particle.pt(), pos); + } + + for (const auto& RecCol : RecCols) { + if (!isEventSelected(RecCol)) { + continue; + } + if (std::abs(RecCol.posZ()) >= cfgevtsel.cfgVtxCut) { + continue; + } + if (cfgevtsel.isApplyBestCollIndex && RecCol.globalIndex() != mcCollision.bestCollisionIndex()) { + continue; + } + auto recTracksPart = RecTracks.sliceBy(perColMidtrack, RecCol.globalIndex()); + for (const auto& track : recTracksPart) { + if (!track.isGlobalTrack()) + continue; + if (!myTrackFilter.IsSelected(track)) + continue; + if (!track.has_mcParticle()) + continue; + auto particle = track.mcParticle(); + if (RecCol.mcCollisionId() != particle.mcCollisionId()) + continue; + if (particle.isPhysicalPrimary()) { + auto pos = std::distance(speciesIds.begin(), std::find(speciesIds.begin(), speciesIds.end(), particle.pdgCode())) + 1; + histos.fill(HIST("hRecMCdndpt"), mcCollision.posZ(), multiplicity, particle.eta(), particle.pt(), pos); + } + } + } + } + + void processMFTtrackEff(ColMCTrueTable::iterator const& mcCollision, ColMCRecTable const& RecCols, + MftTrkMCRecTable const& mfttracks, aod::McParticles const& mcparticles) + { + if (std::abs(mcCollision.posZ()) >= cfgevtsel.cfgVtxCut) { + return; + } + auto multiplicity = 0; + for (const auto& particle : mcparticles) { + if (!isGenPartSelected(particle) || std::abs(particle.eta()) > cfgtrksel.cfgEtaCut || particle.pt() < cfgtrksel.cfgPtCutMin || particle.pt() > cfgtrksel.cfgPtCutMult) + continue; + multiplicity++; + } + if (isUseDataLikeMult > 0) { + for (const auto& RecCol : RecCols) { + if (!isEventSelected(RecCol)) { + continue; + } + if (std::abs(RecCol.posZ()) >= cfgevtsel.cfgVtxCut) { + continue; + } + if (cfgevtsel.isApplyBestCollIndex && RecCol.globalIndex() != mcCollision.bestCollisionIndex()) { + continue; + } + multiplicity = selColCent(RecCol); + } + } + + for (const auto& particle : mcparticles) { + if (!isGenPartSelected(particle) || particle.eta() > cfgmfttrksel.cfigMftEtaMax || particle.eta() < cfgmfttrksel.cfigMftEtaMin || particle.pt() < cfgmfttrksel.cfgMftPtCutMin || particle.pt() > cfgmfttrksel.cfgMftPtCutMax) + continue; + histos.fill(HIST("hGenMCdndpt"), mcCollision.posZ(), multiplicity, particle.eta(), particle.pt(), 1.0); + } + + for (const auto& RecCol : RecCols) { + if (!isEventSelected(RecCol)) { + continue; + } + if (std::abs(RecCol.posZ()) >= cfgevtsel.cfgVtxCut) { + continue; + } + if (cfgevtsel.isApplyBestCollIndex && RecCol.globalIndex() != mcCollision.bestCollisionIndex()) { + continue; + } + auto recTracksPart = mfttracks.sliceBy(perColMfttrack, RecCol.globalIndex()); + for (const auto& track : recTracksPart) { + if (!isMftTrackSelected(track)) + continue; + if (!track.has_mcParticle()) + continue; + auto particle = track.mcParticle(); + if (RecCol.mcCollisionId() != particle.mcCollisionId()) + continue; + if (particle.isPhysicalPrimary()) + histos.fill(HIST("hRecMCdndpt"), mcCollision.posZ(), multiplicity, particle.eta(), particle.pt(), 1.0); + } + } + } + template bool isGenPartSelected(CheckGenPart const& particle) { @@ -945,6 +1107,8 @@ struct LongrangeMaker { PROCESS_SWITCH(LongrangeMaker, processUpc, "process UPC collisions", false); PROCESS_SWITCH(LongrangeMaker, processMCGen, "process MC generated collisions", false); PROCESS_SWITCH(LongrangeMaker, processMCRec, "process MC both gen and rec collisions", false); + PROCESS_SWITCH(LongrangeMaker, processTPCtrackEff, "process TPC track efficiency", false); + PROCESS_SWITCH(LongrangeMaker, processMFTtrackEff, "process MFT track efficiency", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)