From bc0075a2097cca6bc36167b8aef31b9c6411f0ee Mon Sep 17 00:00:00 2001 From: abmodak <67369858+abmodak@users.noreply.github.com> Date: Fri, 17 Apr 2026 21:47:20 +0200 Subject: [PATCH 1/2] Add pT efficiency calculation --- .../TableProducer/longrangeMaker.cxx | 228 +++++++++++++++--- 1 file changed, 198 insertions(+), 30 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx index 25719f7f8f5..605b676358a 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 @@ -72,8 +75,13 @@ using namespace o2::constants::math; auto static constexpr CintZero = 0; auto static constexpr KminFt0cCell = 96; +auto static constexpr PionTrackN = 1; +auto static constexpr KaonTrackN = 2; +auto static constexpr ProtonTrackN = 3; 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 +113,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 +139,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 +178,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 +235,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 +648,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 +677,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) { @@ -755,6 +920,7 @@ struct LongrangeMaker { std::array nSigmaITS = {itsResponse.nSigmaITS(track), itsResponse.nSigmaITS(track), itsResponse.nSigmaITS(track)}; std::array nSigmaToUse = isUseItsPid ? nSigmaITS : nSigmaTPC; // Choose which nSigma to use: TPC or ITS std::vector detectorNsigmaCut = isUseItsPid ? itsNsigmaCut : tpcNsigmaCut; // Choose which nSigma to use: TPC or ITS + int pid = -1; bool isPion, isKaon, isProton; bool isDetectedPion = nSigmaToUse[0] < detectorNsigmaCut[0] && nSigmaToUse[0] > detectorNsigmaCut[0 + 3]; bool isDetectedKaon = nSigmaToUse[1] < detectorNsigmaCut[1] && nSigmaToUse[1] > detectorNsigmaCut[1 + 3]; @@ -945,6 +1111,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) From 920eba37ed1fcc812fdb0ccc9e868c45a95a3069 Mon Sep 17 00:00:00 2001 From: abmodak <67369858+abmodak@users.noreply.github.com> Date: Fri, 17 Apr 2026 21:49:54 +0200 Subject: [PATCH 2/2] Remove unused variable --- .../TwoParticleCorrelations/TableProducer/longrangeMaker.cxx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx index 605b676358a..fcc5cfa15a9 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx @@ -75,9 +75,6 @@ using namespace o2::constants::math; auto static constexpr CintZero = 0; auto static constexpr KminFt0cCell = 96; -auto static constexpr PionTrackN = 1; -auto static constexpr KaonTrackN = 2; -auto static constexpr ProtonTrackN = 3; 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"}; @@ -920,7 +917,6 @@ struct LongrangeMaker { std::array nSigmaITS = {itsResponse.nSigmaITS(track), itsResponse.nSigmaITS(track), itsResponse.nSigmaITS(track)}; std::array nSigmaToUse = isUseItsPid ? nSigmaITS : nSigmaTPC; // Choose which nSigma to use: TPC or ITS std::vector detectorNsigmaCut = isUseItsPid ? itsNsigmaCut : tpcNsigmaCut; // Choose which nSigma to use: TPC or ITS - int pid = -1; bool isPion, isKaon, isProton; bool isDetectedPion = nSigmaToUse[0] < detectorNsigmaCut[0] && nSigmaToUse[0] > detectorNsigmaCut[0 + 3]; bool isDetectedKaon = nSigmaToUse[1] < detectorNsigmaCut[1] && nSigmaToUse[1] > detectorNsigmaCut[1 + 3];