From 8b9a91d41847a511c544a93a24279a30cddc1aaa Mon Sep 17 00:00:00 2001 From: abmodak <67369858+abmodak@users.noreply.github.com> Date: Sun, 14 Jun 2026 19:24:08 +0200 Subject: [PATCH 1/4] Add usage of inner and outer rings of FIT detectors --- .../DataModel/LongRangeDerived.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h b/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h index 62f906a38ae..a6c9e2286ce 100644 --- a/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h +++ b/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h @@ -117,7 +117,8 @@ DECLARE_SOA_TABLE(UpcLRCollisions, "AOD", "UPCLRCOLLISION", lrcorrcolltable::Multiplicity, lrcorrcolltable::TotalFT0AmplitudeA, lrcorrcolltable::TotalFT0AmplitudeC, - lrcorrcolltable::TotalFV0AmplitudeA); + lrcorrcolltable::TotalFV0AmplitudeA, + timestamp::Timestamp); using UpcLRCollision = UpcLRCollisions::iterator; DECLARE_SOA_TABLE(UpcSgLRCollisions, "AOD", "UPCSGLRCOLLISION", @@ -159,6 +160,7 @@ DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(Phi, phi, float); DECLARE_SOA_COLUMN(IsCA, isCA, bool); DECLARE_SOA_COLUMN(IsReassigned, isReassigned, bool); +DECLARE_SOA_COLUMN(IsTrackFT0Outer, isTrackFT0Outer, bool); enum TrackPid { kSpCharge, @@ -193,7 +195,8 @@ DECLARE_SOA_TABLE(LRFt0aTracks, "AOD", "LRFT0ATRACK", lrcorrtrktable::ChannelID, lrcorrtrktable::Amplitude, lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + lrcorrtrktable::Phi, + lrcorrtrktable::IsTrackFT0Outer); using LRFt0aTrack = LRFt0aTracks::iterator; DECLARE_SOA_TABLE(LRFt0cTracks, "AOD", "LRFT0CTRACK", @@ -202,7 +205,8 @@ DECLARE_SOA_TABLE(LRFt0cTracks, "AOD", "LRFT0CTRACK", lrcorrtrktable::ChannelID, lrcorrtrktable::Amplitude, lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + lrcorrtrktable::Phi, + lrcorrtrktable::IsTrackFT0Outer); using LRFt0cTrack = LRFt0cTracks::iterator; DECLARE_SOA_TABLE(LRV0Tracks, "AOD", "LRV0TRACK", @@ -250,7 +254,8 @@ DECLARE_SOA_TABLE(UpcLRFt0aTracks, "AOD", "UPCLRFT0ATRACK", lrcorrtrktable::ChannelID, lrcorrtrktable::Amplitude, lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + lrcorrtrktable::Phi, + lrcorrtrktable::IsTrackFT0Outer); using UpcLRFt0aTrack = UpcLRFt0aTracks::iterator; DECLARE_SOA_TABLE(UpcLRFt0cTracks, "AOD", "UPCLRFT0CTRACK", @@ -259,7 +264,8 @@ DECLARE_SOA_TABLE(UpcLRFt0cTracks, "AOD", "UPCLRFT0CTRACK", lrcorrtrktable::ChannelID, lrcorrtrktable::Amplitude, lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + lrcorrtrktable::Phi, + lrcorrtrktable::IsTrackFT0Outer); using UpcLRFt0cTrack = UpcLRFt0cTracks::iterator; DECLARE_SOA_TABLE(UpcLRV0Tracks, "AOD", "UPCLRV0TRACK", From 45f6c70cc7869ad5514a584e3e90af65bc5f9033 Mon Sep 17 00:00:00 2001 From: abmodak <67369858+abmodak@users.noreply.github.com> Date: Sun, 14 Jun 2026 19:28:38 +0200 Subject: [PATCH 2/4] Add efficiency correction and FIT acceptance correction due to presence of dead channels --- .../TableProducer/longrangeMaker.cxx | 345 +++++++++--------- 1 file changed, 176 insertions(+), 169 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx index 0eaaf4a4f82..4f7979408b3 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx @@ -39,6 +39,7 @@ #include #include +#include #include #include #include @@ -83,11 +84,20 @@ using namespace o2::constants::math; auto static constexpr CintZero = 0; auto static constexpr KminFt0cCell = 96; auto static constexpr TotFt0Channels = 208; +auto static constexpr MinFt0aDeadChannelOuter = 60; +auto static constexpr MinFt0aMirrorChannelOuter = 92; +auto static constexpr MaxFt0aMirrorChannelOuter = 95; +auto static constexpr MinFt0aOuterRing = 32; +auto static constexpr Ft0cDeadChannelInner = 139; +auto static constexpr Ft0cMirrorChannelInner = 115; +auto static constexpr MinFt0cDeadChannelOuter = 176; +auto static constexpr MinFt0cMirrorChannelOuter = 144; +auto static constexpr MaxFt0cMirrorChannelOuter = 147; +auto static constexpr MinFt0cOuterRing = 144; + AxisSpec axisEvent{20, 0.5, 20.5, "#Event", "EventAxis"}; AxisSpec axisTrackSel{10, 0.5, 10.5, "#Track", "TrackAxis"}; auto static constexpr KminCharge = 3.0f; -static constexpr std::string_view species[] = {"Pi", "Ka", "Pr"}; -static constexpr std::array speciesIds{kPiPlus, kKPlus, kProton}; enum KindOfV0 { kLambda = 0, @@ -128,7 +138,6 @@ struct LongrangeMaker { } cfgevtsel; struct : ConfigurableGroup { - Configurable cfgItsPattern{"cfgItsPattern", 1, "0 = Run3ITSibAny, 1 = Run3ITSallAny, 2 = Run3ITSall7Layers, 3 = Run3ITSibTwo"}; Configurable cfgEtaCut{"cfgEtaCut", 0.8f, "Eta range to consider"}; Configurable cfgPtCutMin{"cfgPtCutMin", 0.2f, "minimum accepted track pT"}; Configurable cfgPtCutMax{"cfgPtCutMax", 10.0f, "maximum accepted track pT"}; @@ -140,12 +149,13 @@ struct LongrangeMaker { Configurable maxChi2PerClusterITS{"maxChi2PerClusterITS", 36.f, "cut on maximum value of ITS chi2 per cluster"}; Configurable maxDcaZ{"maxDcaZ", 2.0f, "cut on maximum abs value of DCA z"}; Configurable maxDcaXY{"maxDcaXY", 1.0f, "cut on maximum abs value of DCA xy"}; + Configurable cfgLowEffCut{"cfgLowEffCut", 0.001f, "Low efficiency cut"}; + Configurable applyEffCorr{"applyEffCorr", true, "Enable efficiency correction"}; + Configurable cfgEffccdbPath{"cfgEffccdbPath", "/alice/data/CCDB/Users/a/abmodak/OO/Efficiency", "Browse track eff object from CCDB"}; } cfgtrksel; struct : ConfigurableGroup { Configurable cfgUseChi2Cut{"cfgUseChi2Cut", false, "Use condition on MFT track: chi2/Nclusters"}; - Configurable cfgRequireCA{"cfgRequireCA", false, "Use Cellular Automaton track-finding algorithm"}; - Configurable cfgRequireLTF{"cfgRequireLTF", false, "Use LTF track-finding algorithm"}; Configurable useMftPtCut{"useMftPtCut", true, "Choose to apply MFT track pT cut"}; Configurable cfgMftCluster{"cfgMftCluster", 5, "cut on MFT Cluster"}; Configurable cfgMftEtaMax{"cfgMftEtaMax", -2.4f, "Maximum MFT eta cut"}; @@ -164,6 +174,8 @@ struct LongrangeMaker { Configurable cfgFt0cEtaMin{"cfgFt0cEtaMin", -3.3f, "Minimum FT0C eta cut"}; Configurable cfgVerbosity{"cfgVerbosity", 0, "print statement"}; Configurable useGainCalib{"useGainCalib", true, "use gain calibration"}; + Configurable applyMirrorFt0a{"applyMirrorFt0a", true, "consider Mirror 92-95 into 60-63"}; + Configurable applyMirrorFt0c{"applyMirrorFt0c", true, "consider Mirror 144-147 into 176-179 and Mirror 115 into 139"}; Configurable confGainPath{"confGainPath", "Analysis/EventPlane/GainEq/FT0", "Path to gain calibration"}; } cfgfittrksel; @@ -195,14 +207,11 @@ struct LongrangeMaker { } cfgv0trksel; struct : ConfigurableGroup { - ConfigurableAxis axisVtx = {"axisVtx", {20, -10, 10}, "Vertex axis"}; - ConfigurableAxis axisMult = {"axisMult", {100, 0, 100}, "Multiplicity axis"}; - ConfigurableAxis axisEta = {"axisEta", {20, -1, 1}, "eta axis"}; - ConfigurableAxis axisPt = {"axisPt", {10, 0, 10}, "pT axis"}; - ConfigurableAxis axisSpecies = {"axisSpecies", {4, 0.5, 4.5}, "Species axis"}; ConfigurableAxis axisAmplitude{"axisAmplitude", {5000, 0, 10000}, "FT0 amplitude"}; ConfigurableAxis axisChannel{"axisChannel", {208, 0, 208}, "FT0 channel"}; ConfigurableAxis axisMFTAmbDegree{"axisMFTAmbDegree", {50, -0.5, 49.5}, "Track Ambiguity axis"}; + ConfigurableAxis axisEta = {"axisEta", {100, -5, 5}, "eta axis"}; + ConfigurableAxis axisPhi{"axisPhi", {72, 0, TwoPI}, "#phi axis"}; } cfgAxis; Configurable> itsNsigmaPidCut{"itsNsigmaPidCut", std::vector{3, 2.5, 2, -3, -2.5, -2}, "ITS n-sigma cut for pions_posNsigma, kaons_posNsigma, protons_posNsigma, pions_negNsigma, kaons_negNsigma, protons_negNsigma"}; @@ -210,7 +219,6 @@ 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 isUseCentEst{"isUseCentEst", false, "Centrality based classification"}; Service ccdb; Service pdg; @@ -232,6 +240,10 @@ struct LongrangeMaker { Configurable sgCuts{"sgCuts", {}, "SG event cuts"}; Configurable cfgGapSide{"cfgGapSide", 2, "cut on UPC events"}; + // corrections + TH3D* hTrkEff = nullptr; + bool fLoadTrkEffCorr = false; + void init(InitContext&) { ccdb->setURL(cfgCcdbParam.cfgURL); @@ -261,7 +273,8 @@ struct LongrangeMaker { x->SetBinLabel(12, "ApplyNoCollInTimeRangeStrict"); x->SetBinLabel(13, "ApplyNoHighMultCollInPrevRof"); x->SetBinLabel(14, "ApplyOccupancySelection"); - x->SetBinLabel(15, "reject flange event"); + x->SetBinLabel(15, "ZvertexSelection"); + x->SetBinLabel(16, "reject flange event"); histos.add("hSelectionResult", "hSelectionResult", kTH1I, {{5, -0.5, 4.5}}); histos.add("hMftTrkSel", "hMftTrkSel", kTH1D, {axisTrackSel}, false); @@ -287,28 +300,18 @@ struct LongrangeMaker { histos.add("FT0A_Amp_gaincorrected", "FT0A_Amp_gaincorrected", kTH1D, {cfgAxis.axisAmplitude}); histos.add("FT0A_Channel_vs_Amp", "FT0A_Channel_vs_Amp", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); histos.add("FT0A_Channel_vs_Amp_gaincorrected", "FT0A_Channel_vs_Amp_gaincorrected", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); + histos.add("FT0A_Channel_vs_eta", "FT0A_Channel_vs_eta", kTH2D, {cfgAxis.axisEta, cfgAxis.axisChannel}); + histos.add("FT0A_Channel_vs_phi", "FT0A_Channel_vs_phi", kTH2D, {cfgAxis.axisPhi, cfgAxis.axisChannel}); histos.add("FT0C_Amp", "FT0C_Amp", kTH1D, {cfgAxis.axisAmplitude}); histos.add("FT0C_Amp_gaincorrected", "FT0C_Amp_gaincorrected", kTH1D, {cfgAxis.axisAmplitude}); histos.add("FT0C_Channel_vs_Amp", "FT0C_Channel_vs_Amp", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); histos.add("FT0C_Channel_vs_Amp_gaincorrected", "FT0C_Channel_vs_Amp_gaincorrected", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); + histos.add("FT0C_Channel_vs_eta", "FT0C_Channel_vs_eta", kTH2D, {cfgAxis.axisEta, cfgAxis.axisChannel}); + histos.add("FT0C_Channel_vs_phi", "FT0C_Channel_vs_phi", kTH2D, {cfgAxis.axisPhi, cfgAxis.axisChannel}); - if (doprocessTPCtrackEff || doprocessMFTtrackEff) { - histos.add("hGenMCdndpt", "hGenMCdndpt", kTHnSparseD, {cfgAxis.axisVtx, cfgAxis.axisMult, cfgAxis.axisEta, cfgAxis.axisPt, cfgAxis.axisSpecies}, false); - histos.add("hRecMCdndpt", "hRecMCdndpt", kTHnSparseD, {cfgAxis.axisVtx, cfgAxis.axisMult, cfgAxis.axisEta, cfgAxis.axisPt, cfgAxis.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(4, "Other"); - axisRec->SetBinLabel(4, "Other"); - } - - myTrackFilter = getGlobalTrackSelectionRun3ITSMatch(cfgtrksel.cfgItsPattern, TrackSelection::GlobalTrackRun3DCAxyCut::Default); + myTrackFilter = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, + TrackSelection::GlobalTrackRun3DCAxyCut::Default); myTrackFilter.SetPtRange(cfgtrksel.cfgPtCutMin, cfgtrksel.cfgPtCutMax); myTrackFilter.SetEtaRange(-cfgtrksel.cfgEtaCut, cfgtrksel.cfgEtaCut); myTrackFilter.SetMinNCrossedRowsTPC(cfgtrksel.minNCrossedRowsTPC); @@ -368,9 +371,8 @@ struct LongrangeMaker { if (!isEventSelected(col)) { return; } - auto multiplicity = countNTracks(tracks); - auto centrality = selColCent(col); auto bc = col.bc_as(); + loadEffCorrection(bc.timestamp()); // retrieve FT0 gain info from CCDB ft0gainvalues.clear(); ft0gainvalues = {}; @@ -388,6 +390,8 @@ struct LongrangeMaker { ft0gainvalues.push_back(1.); } } + auto multiplicity = countNTracks(tracks, col.posZ()); + auto centrality = selColCent(col); lrcollision(bc.runNumber(), col.posZ(), multiplicity, centrality, bc.timestamp()); // track loop @@ -430,7 +434,7 @@ struct LongrangeMaker { return; } } - histos.fill(HIST("EventHist"), 15); + histos.fill(HIST("EventHist"), 16); for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { auto chanelid = ft0.channelA()[iCh]; float ampl = ft0.amplitudeA()[iCh]; @@ -447,11 +451,25 @@ struct LongrangeMaker { chanelid, gainampl, eta, - phi); + phi, + chanelid >= MinFt0aOuterRing); + if (cfgfittrksel.applyMirrorFt0a) { + int mirrorId = getFt0aDeadChannelId(chanelid); + if (mirrorId >= 0) { + lrft0atracks(lrcollision.lastIndex(), + mirrorId, + gainampl, + getEtaFT0(mirrorId, 0), + getPhiFT0(mirrorId, 0), + mirrorId >= MinFt0aOuterRing); + } + } histos.fill(HIST("FT0A_Amp"), ampl); histos.fill(HIST("FT0A_Channel_vs_Amp"), chanelid, ampl); histos.fill(HIST("FT0A_Amp_gaincorrected"), gainampl); histos.fill(HIST("FT0A_Channel_vs_Amp_gaincorrected"), chanelid, gainampl); + histos.fill(HIST("FT0A_Channel_vs_eta"), eta, chanelid); + histos.fill(HIST("FT0A_Channel_vs_phi"), phi, chanelid); } for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { auto chanelid = ft0.channelC()[iCh] + KminFt0cCell; @@ -469,11 +487,25 @@ struct LongrangeMaker { chanelid, gainampl, eta, - phi); + phi, + chanelid >= MinFt0cOuterRing); + if (cfgfittrksel.applyMirrorFt0c) { + int mirrorId = getFt0cDeadChannelId(chanelid); + if (mirrorId >= 0) { + lrft0ctracks(lrcollision.lastIndex(), + mirrorId, + gainampl, + getEtaFT0(mirrorId, 1), + getPhiFT0(mirrorId, 1), + mirrorId >= MinFt0cOuterRing); + } + } histos.fill(HIST("FT0C_Amp"), ampl); histos.fill(HIST("FT0C_Channel_vs_Amp"), chanelid, ampl); histos.fill(HIST("FT0C_Amp_gaincorrected"), gainampl); histos.fill(HIST("FT0C_Channel_vs_Amp_gaincorrected"), chanelid, gainampl); + histos.fill(HIST("FT0C_Channel_vs_eta"), eta, chanelid); + histos.fill(HIST("FT0C_Channel_vs_phi"), phi, chanelid); } } @@ -566,6 +598,7 @@ struct LongrangeMaker { } auto bc = col.template foundBC_as(); + loadEffCorrection(bc.timestamp()); auto newbc = bc; // obtain slice of compatible BCs auto bcRange = udhelpers::compatibleBCs(col, cfgSgCuts.NDtcoll(), bcs, cfgSgCuts.minNBCs()); @@ -581,8 +614,8 @@ struct LongrangeMaker { upchelpers::FITInfo fitInfo{}; udhelpers::getFITinfo(fitInfo, newbc, bcs, ft0s, fv0as, fdds); - auto multiplicity = countNTracks(tracks); - upclrcollision(bc.globalBC(), bc.runNumber(), col.posZ(), multiplicity, fitInfo.ampFT0A, fitInfo.ampFT0C, fitInfo.timeFV0A); + auto multiplicity = countNTracks(tracks, col.posZ()); + upclrcollision(bc.globalBC(), bc.runNumber(), col.posZ(), multiplicity, fitInfo.ampFT0A, fitInfo.ampFT0C, fitInfo.timeFV0A, bc.timestamp()); upcsglrcollision(issgevent); if (newbc.has_zdc()) { auto zdc = newbc.zdc(); @@ -636,7 +669,8 @@ struct LongrangeMaker { chanelid, ampl, eta, - phi); + phi, + chanelid >= MinFt0aOuterRing); } for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { auto chanelid = ft0.channelC()[iCh] + KminFt0cCell; @@ -650,7 +684,8 @@ struct LongrangeMaker { chanelid, ampl, eta, - phi); + phi, + chanelid >= MinFt0cOuterRing); } } @@ -753,10 +788,8 @@ struct LongrangeMaker { if (cfgevtsel.isApplyBestCollIndex && RecCol.globalIndex() != mcCollision.bestCollisionIndex()) { continue; } - auto recTracksPart = RecTracks.sliceBy(perColMidtrack, RecCol.globalIndex()); - auto multiplicity = countNTracks(recTracksPart); - auto centrality = selColCent(RecCol); auto bc = RecCol.bc_as(); + loadEffCorrection(bc.timestamp()); ft0gainvalues.clear(); ft0gainvalues = {}; if (cfgfittrksel.useGainCalib) { @@ -773,6 +806,9 @@ struct LongrangeMaker { ft0gainvalues.push_back(1.); } } + auto recTracksPart = RecTracks.sliceBy(perColMidtrack, RecCol.globalIndex()); + auto multiplicity = countNTracks(recTracksPart, RecCol.posZ()); + auto centrality = selColCent(RecCol); lrcollision(bc.runNumber(), RecCol.posZ(), multiplicity, centrality, bc.timestamp()); lrcollisionMcLabel(RecCol.mcCollisionId()); @@ -827,11 +863,25 @@ struct LongrangeMaker { chanelid, gainampl, eta, - phi); + phi, + chanelid >= MinFt0aOuterRing); + if (cfgfittrksel.applyMirrorFt0a) { + int mirrorId = getFt0aDeadChannelId(chanelid); + if (mirrorId >= 0) { + lrft0atracks(lrcollision.lastIndex(), + mirrorId, + gainampl, + getEtaFT0(mirrorId, 0), + getPhiFT0(mirrorId, 0), + mirrorId >= MinFt0aOuterRing); + } + } histos.fill(HIST("FT0A_Amp"), ampl); histos.fill(HIST("FT0A_Channel_vs_Amp"), chanelid, ampl); histos.fill(HIST("FT0A_Amp_gaincorrected"), gainampl); histos.fill(HIST("FT0A_Channel_vs_Amp_gaincorrected"), chanelid, gainampl); + histos.fill(HIST("FT0A_Channel_vs_eta"), chanelid, eta); + histos.fill(HIST("FT0A_Channel_vs_phi"), chanelid, phi); } for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { auto chanelid = ft0.channelC()[iCh] + KminFt0cCell; @@ -846,11 +896,25 @@ struct LongrangeMaker { chanelid, gainampl, eta, - phi); + phi, + chanelid >= MinFt0cOuterRing); + if (cfgfittrksel.applyMirrorFt0c) { + int mirrorId = getFt0cDeadChannelId(chanelid); + if (mirrorId >= 0) { + lrft0ctracks(lrcollision.lastIndex(), + mirrorId, + gainampl, + getEtaFT0(mirrorId, 1), + getPhiFT0(mirrorId, 1), + mirrorId >= MinFt0cOuterRing); + } + } histos.fill(HIST("FT0C_Amp"), ampl); histos.fill(HIST("FT0C_Channel_vs_Amp"), chanelid, ampl); histos.fill(HIST("FT0C_Amp_gaincorrected"), gainampl); histos.fill(HIST("FT0C_Channel_vs_Amp_gaincorrected"), chanelid, gainampl); + histos.fill(HIST("FT0C_Channel_vs_eta"), chanelid, eta); + histos.fill(HIST("FT0C_Channel_vs_phi"), chanelid, phi); } } @@ -895,15 +959,22 @@ struct LongrangeMaker { } } - void processMCGen(ColMCTrueTable::iterator const& mcCollision, aod::McParticles const& mcparticles) + void processMCGen(aod::McCollisions::iterator const& mcCollision, aod::McParticles const& mcparticles) { auto multiplicity = 0; + auto multMCFT0A = 0; + auto multMCFT0C = 0; for (const auto& particle : mcparticles) { - if (!isGenPartSelected(particle) || std::abs(particle.eta()) > cfgtrksel.cfgEtaCut || particle.pt() < cfgtrksel.cfgPtCutMin || particle.pt() > cfgtrksel.cfgPtCutMult) + if (!isGenPartSelected(particle)) continue; - multiplicity++; + if (std::abs(particle.eta()) < cfgtrksel.cfgEtaCut && particle.pt() > cfgtrksel.cfgPtCutMin && particle.pt() < cfgtrksel.cfgPtCutMult) + multiplicity++; + if (cfgfittrksel.cfgFt0cEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfgFt0cEtaMax) + multMCFT0C++; + if (cfgfittrksel.cfgFt0aEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfgFt0aEtaMax) + multMCFT0A++; } - lrmccollision(mcCollision.posZ(), multiplicity, mcCollision.multMCFT0A(), mcCollision.multMCFT0C()); + lrmccollision(mcCollision.posZ(), multiplicity, multMCFT0A, multMCFT0C); for (const auto& particle : mcparticles) { if (!isGenPartSelected(particle)) { @@ -923,125 +994,6 @@ struct LongrangeMaker { } } - 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; - bool atLeastOne = false; - 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; - if (isUseCentEst) { - multiplicity = selColCent(RecCol); - } else { - auto recTracksPart = RecTracks.sliceBy(perColMidtrack, RecCol.globalIndex()); - multiplicity = countNTracks(recTracksPart); - } - atLeastOne = true; - } - for (const auto& particle : mcparticles) { - if (!isGenPartSelected(particle) || std::abs(particle.eta()) > cfgtrksel.cfgEtaCut || particle.pt() < cfgtrksel.cfgPtCutMin || particle.pt() > cfgtrksel.cfgPtCutMax) - continue; - if (atLeastOne) { - 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, - TrksMCRecTable const& RecTracks, MftTrkMCRecTable const&, - aod::BestCollisionsFwd3d const& reassoMftTracks, aod::McParticles const& mcparticles) - { - if (std::abs(mcCollision.posZ()) >= cfgevtsel.cfgVtxCut) { - return; - } - auto multiplicity = 0; - bool atLeastOne = false; - 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; - if (isUseCentEst) { - multiplicity = selColCent(RecCol); - } else { - auto recTracksPart = RecTracks.sliceBy(perColMidtrack, RecCol.globalIndex()); - multiplicity = countNTracks(recTracksPart); - } - atLeastOne = true; - } - for (const auto& particle : mcparticles) { - if (!isGenPartSelected(particle) || particle.eta() > cfgmfttrksel.cfgMftEtaMax || particle.eta() < cfgmfttrksel.cfgMftEtaMin || particle.pt() < cfgmfttrksel.cfgMftPtCutMin || particle.pt() > cfgmfttrksel.cfgMftPtCutMax) - continue; - if (atLeastOne) - 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 = reassoMftTracks.sliceBy(perColMftTrack, RecCol.globalIndex()); - for (const auto& reassoMftTrack : recTracksPart) { - if (!isMftBestTrackSelected(reassoMftTrack)) - continue; - auto track = reassoMftTrack.mfttrack_as(); - if (!isMftTrackSelected(track)) { - continue; - } - if (cfgmfttrksel.cfgRequireCA && !track.isCA()) { - continue; - } - if (cfgmfttrksel.cfgRequireLTF && track.isCA()) { - 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) { @@ -1117,11 +1069,15 @@ struct LongrangeMaker { return false; } histos.fill(HIST("EventHist"), 14); + if (std::abs(col.posZ()) >= cfgevtsel.cfgVtxCut) { + return false; + } + histos.fill(HIST("EventHist"), 15); return true; } template - int countNTracks(countTrk const& tracks) + int countNTracks(countTrk const& tracks, float vz) { auto nTrk = 0; for (const auto& track : tracks) { @@ -1132,7 +1088,10 @@ struct LongrangeMaker { if (track.pt() < cfgtrksel.cfgPtCutMin || track.pt() > cfgtrksel.cfgPtCutMult) { continue; } - nTrk++; + float trkeff = 1.0f; + if (cfgtrksel.applyEffCorr) + trkeff = getTrkEffCorr(vz, track.eta(), track.pt()); + nTrk += 1.0 / trkeff; } return nTrk; } @@ -1201,6 +1160,24 @@ struct LongrangeMaker { } } + int getFt0aDeadChannelId(int channelId) + { + if (channelId >= MinFt0aMirrorChannelOuter && channelId <= MaxFt0aMirrorChannelOuter) + return MinFt0aDeadChannelOuter + (channelId - MinFt0aMirrorChannelOuter); + else + return -1; + } + + int getFt0cDeadChannelId(int channelId) + { + if (channelId >= MinFt0cMirrorChannelOuter && channelId <= MaxFt0cMirrorChannelOuter) + return MinFt0cDeadChannelOuter + (channelId - MinFt0cMirrorChannelOuter); + else if (channelId == Ft0cMirrorChannelInner) + return Ft0cDeadChannelInner; + else + return -1; + } + double getPhiFT0(uint chno, int i) { ft0Det.calculateChannelCenter(); @@ -1390,12 +1367,42 @@ struct LongrangeMaker { return true; } + void loadEffCorrection(uint64_t timestamp) + { + if (fLoadTrkEffCorr) { + return; + } + if (cfgtrksel.cfgEffccdbPath.value.empty() == false) { + hTrkEff = ccdb->getForTimeStamp(cfgtrksel.cfgEffccdbPath, timestamp); + if (hTrkEff == nullptr) { + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgtrksel.cfgEffccdbPath.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgtrksel.cfgEffccdbPath.value.c_str(), (void*)hTrkEff); + } + fLoadTrkEffCorr = true; + } + + float getTrkEffCorr(float posZ, float eta, float pt) + { + float eff = 1.; + if (hTrkEff) { + int zBin = hTrkEff->GetXaxis()->FindBin(posZ); + int etaBin = hTrkEff->GetYaxis()->FindBin(eta); + int ptBin = hTrkEff->GetZaxis()->FindBin(pt); + eff = hTrkEff->GetBinContent(zBin, etaBin, ptBin); + } else { + eff = 1.0; + } + if (eff < cfgtrksel.cfgLowEffCut) + eff = 1.0; + + return eff; + } + PROCESS_SWITCH(LongrangeMaker, processData, "process All collisions", false); 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 16c4eefd04dc17cccdadd584cec532f549f592f7 Mon Sep 17 00:00:00 2001 From: abmodak <67369858+abmodak@users.noreply.github.com> Date: Sun, 14 Jun 2026 19:33:20 +0200 Subject: [PATCH 3/4] Add Efficiency correction --- .../Tasks/longrangecorrDerived.cxx | 327 ++++++++++++++---- 1 file changed, 265 insertions(+), 62 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx b/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx index 36e1e416722..b89a9885108 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx @@ -19,8 +19,15 @@ #include "PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h" #include "PWGUD/Core/SGSelector.h" +#include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/McCollisionExtra.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include #include #include #include @@ -31,6 +38,7 @@ #include #include #include +#include #include #include @@ -51,11 +59,16 @@ using namespace o2::aod::fwdtrack; using namespace o2::aod::evsel; using namespace o2::constants::math; +auto static constexpr KminCharge = 3.0f; + struct LongrangecorrDerived { SliceCache cache; SGSelector sgSelector; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + TrackSelection myTrackFilter; + Service pdg; + Service ccdb; struct : ConfigurableGroup { Configurable cfgNmixedevent{"cfgNmixedevent", 5, "how many events are mixed"}; @@ -65,11 +78,18 @@ struct LongrangecorrDerived { Configurable cfgVtxCut{"cfgVtxCut", 10.0f, "Vertex Z range to consider"}; Configurable isUseCentEst{"isUseCentEst", false, "Centrality based classification"}; Configurable isUseDataLikeMult{"isUseDataLikeMult", 0, "Data like mult/cent classification"}; + Configurable cfgVerbosity{"cfgVerbosity", 0, "print statement"}; + Configurable cfgEtaCut{"cfgEtaCut", 0.8f, "Eta range to consider"}; + Configurable cfgPtCutMin{"cfgPtCutMin", 0.2f, "minimum accepted track pT"}; + Configurable cfgPtCutMax{"cfgPtCutMax", 10.0f, "maximum accepted track pT"}; Configurable cfgTpcMinNclsFound{"cfgTpcMinNclsFound", 50.0f, ""}; Configurable cfgTpcMinNCrossedRows{"cfgTpcMinNCrossedRows", 70.0f, ""}; Configurable cfgTpcMaxChi2PerCluster{"cfgTpcMaxChi2PerCluster", 4.0f, ""}; Configurable cfgTpcMaxDcaZ{"cfgTpcMaxDcaZ", 1.0f, ""}; + Configurable cfgLowEffCut{"cfgLowEffCut", 0.001f, "Low efficiency cut"}; + Configurable applyEffCorr{"applyEffCorr", true, "Enable efficiency correction"}; + Configurable cfgEffccdbPath{"cfgEffccdbPath", "Users/a/abmodak/Efficiency/OO/default", "Browse track eff object from CCDB"}; Configurable cfgMftCluster{"cfgMftCluster", 5, "cut on MFT Cluster"}; Configurable cfgMftDcaxy{"cfgMftDcaxy", 2.0f, "cut on DCA xy for MFT tracks"}; @@ -78,9 +98,14 @@ struct LongrangecorrDerived { Configurable cfgRejectNonAmbTrk{"cfgRejectNonAmbTrk", false, "Condition to reject Non-Ambiguous tracks"}; Configurable cfgRequireCA{"cfgRequireCA", false, "Use Cellular Automaton track-finding algorithm"}; Configurable cfgRequireLTF{"cfgRequireLTF", false, "Use LTF track-finding algorithm"}; + Configurable cfgRequireFt0aOuterRing{"cfgRequireFt0aOuterRing", false, "Consider FT0A Outer Ring"}; + Configurable cfgRequireFt0aInnerRing{"cfgRequireFt0aInnerRing", false, "Consider FT0A Inner Ring"}; + Configurable cfgRequireFt0cOuterRing{"cfgRequireFt0cOuterRing", false, "Consider FT0C Outer Ring"}; + Configurable cfgRequireFt0cInnerRing{"cfgRequireFt0cInnerRing", false, "Consider FT0C Inner Ring"}; } cfgSel; struct : ConfigurableGroup { + ConfigurableAxis axisMultQA{"axisMultQA", {500, -0.5, 499.5}, "multiplicity QA axis"}; ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 10, 15, 25, 50, 60, 1000}, "multiplicity axis"}; ConfigurableAxis axisPhi{"axisPhi", {96, 0, TwoPI}, "#phi axis"}; ConfigurableAxis axisEtaTrig{"axisEtaTrig", {40, -1., 1.}, "#eta trig axis"}; @@ -121,6 +146,10 @@ struct LongrangecorrDerived { OutputObj same{"sameEvent"}; OutputObj mixed{"mixedEvent"}; + // corrections + TH3D* hTrkEff = nullptr; + bool fLoadTrkEffCorr = false; + using CollsTable = aod::LRCollisions; using TrksTable = aod::LRMidTracks; using MftTrksTable = aod::LRMftTracks; @@ -171,46 +200,97 @@ struct LongrangecorrDerived { {cfgAxis.axisEtaEfficiency, "#eta"}}; std::vector userAxis = {{cfgAxis.axisInvMass, "m (GeV/c^2)"}}; - same.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); - mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); - - histos.add("hMultiplicity", "hMultiplicity", kTH1D, {cfgAxis.axisMultiplicity}); - histos.add("hCentrality", "hCentrality", kTH1D, {cfgAxis.axisMultiplicity}); - histos.add("hVertexZ", "hVertexZ", kTH1D, {cfgAxis.axisVtxZ}); - - histos.add("hGapSide", "hGapSide", kTH1I, {{5, -0.5, 4.5}}); - histos.add("hTrueGapSide", "hTrueGapSide", kTH1I, {{6, -1.5, 4.5}}); - histos.add("hTrueGapSide_AfterSel", "hTrueGapSide_AfterSel", kTH1I, {{6, -1.5, 4.5}}); - - histos.add("Trig_eta", "Trig_eta", kTH1D, {cfgAxis.axisEtaTrig}); - histos.add("Trig_phi", "Trig_phi", kTH1D, {cfgAxis.axisPhi}); - histos.add("Trig_etavsphi", "Trig_etavsphi", kTH2D, {cfgAxis.axisPhi, cfgAxis.axisEtaTrig}); - histos.add("Trig_pt", "Trig_pt", kTH1D, {cfgAxis.axisPtTrigger}); - histos.add("Trig_invMass", "Trig_invMass", kTH1D, {cfgAxis.axisInvMassQA}); - histos.add("Trig_hist", "Trig_hist", kTHnSparseF, {cfgAxis.axisSample, cfgAxis.axisVtxZ, cfgAxis.axisMultiplicity, cfgAxis.axisPtTrigger, cfgAxis.axisInvMass}); - histos.add("Trig_amp", "Trig_amp", kTH1D, {cfgAxis.axisAmplitude}); - histos.add("Channel_vs_Trig_amp", "Channel_vs_Trig_amp", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); - - histos.add("Assoc_eta", "Assoc_eta", kTH1D, {cfgAxis.axisEtaAssoc}); - histos.add("Assoc_phi", "Assoc_phi", kTH1D, {cfgAxis.axisPhi}); - histos.add("Assoc_etavsphi", "Assoc_etavsphi", kTH2D, {cfgAxis.axisPhi, cfgAxis.axisEtaAssoc}); - histos.add("Assoc_amp", "Assoc_amp", kTH1D, {cfgAxis.axisAmplitude}); - histos.add("Channel_vs_Assoc_amp", "Channel_vs_Assoc_amp", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); + if (!(doprocessTPCtrackEff)) { + + same.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); + + histos.add("hMultiplicity", "hMultiplicity", kTH1D, {cfgAxis.axisMultQA}); + histos.add("hCentrality", "hCentrality", kTH1D, {cfgAxis.axisMultQA}); + histos.add("hVertexZ", "hVertexZ", kTH1D, {cfgAxis.axisVtxZ}); + + histos.add("hGapSide", "hGapSide", kTH1I, {{5, -0.5, 4.5}}); + histos.add("hTrueGapSide", "hTrueGapSide", kTH1I, {{6, -1.5, 4.5}}); + histos.add("hTrueGapSide_AfterSel", "hTrueGapSide_AfterSel", kTH1I, {{6, -1.5, 4.5}}); + + histos.add("Trig_eta", "Trig_eta", kTH1D, {cfgAxis.axisEtaTrig}); + histos.add("Trig_eta_corrected", "Trig_eta_corrected", kTH1D, {cfgAxis.axisEtaTrig}); + histos.add("Trig_phi", "Trig_phi", kTH1D, {cfgAxis.axisPhi}); + histos.add("Trig_etavsphi", "Trig_etavsphi", kTH2D, {cfgAxis.axisPhi, cfgAxis.axisEtaTrig}); + histos.add("Trig_pt", "Trig_pt", kTH1D, {cfgAxis.axisPtTrigger}); + histos.add("Trig_pt_corrected", "Trig_pt_corrected", kTH1D, {cfgAxis.axisPtTrigger}); + histos.add("Trig_invMass", "Trig_invMass", kTH1D, {cfgAxis.axisInvMassQA}); + histos.add("Trig_hist", "Trig_hist", kTHnSparseF, {cfgAxis.axisSample, cfgAxis.axisVtxZ, cfgAxis.axisMultiplicity, cfgAxis.axisPtTrigger, cfgAxis.axisInvMass}); + histos.add("Trig_amp", "Trig_amp", kTH1D, {cfgAxis.axisAmplitude}); + histos.add("Channel_vs_Trig_amp", "Channel_vs_Trig_amp", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); + + histos.add("Assoc_eta", "Assoc_eta", kTH1D, {cfgAxis.axisEtaAssoc}); + histos.add("Assoc_phi", "Assoc_phi", kTH1D, {cfgAxis.axisPhi}); + histos.add("Assoc_etavsphi", "Assoc_etavsphi", kTH2D, {cfgAxis.axisPhi, cfgAxis.axisEtaAssoc}); + histos.add("Assoc_amp", "Assoc_amp", kTH1D, {cfgAxis.axisAmplitude}); + histos.add("Channel_vs_Assoc_amp", "Channel_vs_Assoc_amp", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); + + histos.add("deltaEta_deltaPhi_same", "deltaEta_deltaPhi_same", kTH2D, {cfgAxis.axisDeltaPhi, cfgAxis.axisDeltaEta}); + histos.add("deltaEta_deltaPhi_mixed", "deltaEta_deltaPhi_mixed", kTH2D, {cfgAxis.axisDeltaPhi, cfgAxis.axisDeltaEta}); + + histos.add("TPCNClsFound", "TPCNClsFound", kTH1D, {cfgAxis.axisTPCNClsFound}); + histos.add("TPCNClsCrossedRows", "TPCNClsCrossedRows", kTH1D, {cfgAxis.axisTPCNClsCrossedRows}); + histos.add("TPCChi2NCl", "TPCChi2NCl", kTH1D, {cfgAxis.axisTPCChi2NCl}); + histos.add("TPCdcaZ", "TPCdcaZ", kTH1D, {cfgAxis.axisTPCdcaZ}); + + histos.add("MFTNClusters", "MFTNClusters", kTH1D, {cfgAxis.axisMFTNClusters}); + histos.add("MFTbestDCAXY", "MFTbestDCAXY", kTH1D, {cfgAxis.axisMFTbestDCAXY}); + histos.add("MFTbestDCAZ", "MFTbestDCAZ", kTH1D, {cfgAxis.axisMFTbestDCAZ}); + + histos.add("ReassignedMFTtrackAmbDegree", "ReassignedMFTtrackAmbDegree", kTH1D, {cfgAxis.axisMFTAmbDegree}); + histos.add("AssignedMFTtrackAmbDegree", "AssignedMFTtrackAmbDegree", kTH1D, {cfgAxis.axisMFTAmbDegree}); + } - histos.add("deltaEta_deltaPhi_same", "deltaEta_deltaPhi_same", kTH2D, {cfgAxis.axisDeltaPhi, cfgAxis.axisDeltaEta}); - histos.add("deltaEta_deltaPhi_mixed", "deltaEta_deltaPhi_mixed", kTH2D, {cfgAxis.axisDeltaPhi, cfgAxis.axisDeltaEta}); + if (doprocessTPCtrackEff) { + histos.add("hGenMCdndpt", "hGenMCdndpt", kTH3D, {cfgAxis.axisVtxZ, cfgAxis.axisEtaEfficiency, cfgAxis.axisPtEfficiency}); + histos.add("hRecMCdndpt", "hRecMCdndpt", kTH3D, {cfgAxis.axisVtxZ, cfgAxis.axisEtaEfficiency, cfgAxis.axisPtEfficiency}); + } - histos.add("TPCNClsFound", "TPCNClsFound", kTH1D, {cfgAxis.axisTPCNClsFound}); - histos.add("TPCNClsCrossedRows", "TPCNClsCrossedRows", kTH1D, {cfgAxis.axisTPCNClsCrossedRows}); - histos.add("TPCChi2NCl", "TPCChi2NCl", kTH1D, {cfgAxis.axisTPCChi2NCl}); - histos.add("TPCdcaZ", "TPCdcaZ", kTH1D, {cfgAxis.axisTPCdcaZ}); + myTrackFilter = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, + TrackSelection::GlobalTrackRun3DCAxyCut::Default); + myTrackFilter.SetPtRange(cfgSel.cfgPtCutMin, cfgSel.cfgPtCutMax); + myTrackFilter.SetEtaRange(-cfgSel.cfgEtaCut, cfgSel.cfgEtaCut); + myTrackFilter.SetMinNCrossedRowsTPC(cfgSel.cfgTpcMinNCrossedRows); + myTrackFilter.SetMinNClustersTPC(cfgSel.cfgTpcMinNclsFound); + myTrackFilter.SetMaxChi2PerClusterTPC(cfgSel.cfgTpcMaxChi2PerCluster); + myTrackFilter.SetMaxDcaZ(cfgSel.cfgTpcMaxDcaZ); + myTrackFilter.print(); + } - histos.add("MFTNClusters", "MFTNClusters", kTH1D, {cfgAxis.axisMFTNClusters}); - histos.add("MFTbestDCAXY", "MFTbestDCAXY", kTH1D, {cfgAxis.axisMFTbestDCAXY}); - histos.add("MFTbestDCAZ", "MFTbestDCAZ", kTH1D, {cfgAxis.axisMFTbestDCAZ}); + void loadEffCorrection(uint64_t timestamp) + { + if (fLoadTrkEffCorr) { + return; + } + if (cfgSel.cfgEffccdbPath.value.empty() == false) { + hTrkEff = ccdb->getForTimeStamp(cfgSel.cfgEffccdbPath, timestamp); + if (hTrkEff == nullptr) { + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgSel.cfgEffccdbPath.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgSel.cfgEffccdbPath.value.c_str(), (void*)hTrkEff); + } + fLoadTrkEffCorr = true; + } - histos.add("ReassignedMFTtrackAmbDegree", "ReassignedMFTtrackAmbDegree", kTH1D, {cfgAxis.axisMFTAmbDegree}); - histos.add("AssignedMFTtrackAmbDegree", "AssignedMFTtrackAmbDegree", kTH1D, {cfgAxis.axisMFTAmbDegree}); + float getTrkEffCorr(float posZ, float eta, float pt) + { + float eff = 1.0f; + if (hTrkEff) { + int zBin = hTrkEff->GetXaxis()->FindBin(posZ); + int etaBin = hTrkEff->GetYaxis()->FindBin(eta); + int ptBin = hTrkEff->GetZaxis()->FindBin(pt); + eff = hTrkEff->GetBinContent(zBin, etaBin, ptBin); + } else { + eff = 1.0f; + } + if (eff < cfgSel.cfgLowEffCut) + eff = 1.0; + return 1.0 / eff; } template @@ -258,16 +338,18 @@ struct LongrangecorrDerived { } template - void fillTrigTrackQA(TTrack const& track) + void fillTrigTrackQA(TTrack const& track, float trigAmpl, float trkeff) { histos.fill(HIST("Trig_etavsphi"), track.phi(), track.eta()); histos.fill(HIST("Trig_eta"), track.eta()); + histos.fill(HIST("Trig_eta_corrected"), track.eta(), trkeff); histos.fill(HIST("Trig_phi"), track.phi()); if constexpr (requires { track.channelID(); }) { - histos.fill(HIST("Trig_amp"), track.amplitude()); - histos.fill(HIST("Channel_vs_Trig_amp"), track.channelID(), track.amplitude()); + histos.fill(HIST("Trig_amp"), trigAmpl); + histos.fill(HIST("Channel_vs_Trig_amp"), track.channelID(), trigAmpl); } else { histos.fill(HIST("Trig_pt"), track.pt()); + histos.fill(HIST("Trig_pt_corrected"), track.pt(), trkeff); } if constexpr (requires { track.invMass(); }) { histos.fill(HIST("Trig_invMass"), track.invMass()); @@ -291,14 +373,14 @@ struct LongrangecorrDerived { } template - void fillAssocTrackQA(TTrack const& track) + void fillAssocTrackQA(TTrack const& track, float assoAmpl) { histos.fill(HIST("Assoc_etavsphi"), track.phi(), track.eta()); histos.fill(HIST("Assoc_eta"), track.eta()); histos.fill(HIST("Assoc_phi"), track.phi()); if constexpr (requires { track.channelID(); }) { - histos.fill(HIST("Assoc_amp"), track.amplitude()); - histos.fill(HIST("Channel_vs_Assoc_amp"), track.channelID(), track.amplitude()); + histos.fill(HIST("Assoc_amp"), assoAmpl); + histos.fill(HIST("Channel_vs_Assoc_amp"), track.channelID(), assoAmpl); } if constexpr (requires { track.nClusters(); }) { histos.fill(HIST("MFTNClusters"), track.nClusters()); @@ -336,11 +418,7 @@ struct LongrangecorrDerived { int fSampleIndex = gRandom->Uniform(0, cfgSel.cfgSampleSize); for (auto const& triggerTrack : triggers) { auto trigAmpl = 1.0f; - if constexpr (requires { triggerTrack.channelID(); }) { - trigAmpl = triggerTrack.amplitude(); - } else { - trigAmpl = 1.0; - } + auto trkeff = 1.0f; if (!isTrackSelected(triggerTrack)) continue; @@ -352,41 +430,65 @@ struct LongrangecorrDerived { if (cfgSel.cfgV0Mask != 0 && (cfgSel.cfgV0Mask & (1u << static_cast(triggerTrack.v0Type()))) == 0u) continue; } + + if constexpr (requires { triggerTrack.channelID(); }) { + if (cfgSel.cfgRequireFt0aOuterRing && !triggerTrack.isTrackFT0Outer()) + continue; + if (cfgSel.cfgRequireFt0aInnerRing && triggerTrack.isTrackFT0Outer()) + continue; + trigAmpl = triggerTrack.amplitude(); + } else { + trigAmpl = 1.0; + } + + if constexpr (step == CorrelationContainer::kCFStepCorrected) { + if constexpr (requires { triggerTrack.trackType(); }) { + trkeff = getTrkEffCorr(vz, triggerTrack.eta(), triggerTrack.pt()); + } else { + trkeff = 1.0; + } + } + if (!mixing) { - fillTrigTrackQA(triggerTrack); + fillTrigTrackQA(triggerTrack, trigAmpl, trkeff); if constexpr (requires { triggerTrack.channelID(); }) { - histos.fill(HIST("Trig_hist"), fSampleIndex, vz, multiplicity, 1.0, 1.0, eventWeight * trigAmpl); + histos.fill(HIST("Trig_hist"), fSampleIndex, vz, multiplicity, 1.0, 1.0, eventWeight * trigAmpl * trkeff); } else if constexpr (requires { triggerTrack.invMass(); }) { - histos.fill(HIST("Trig_hist"), fSampleIndex, vz, multiplicity, triggerTrack.pt(), triggerTrack.invMass(), eventWeight * trigAmpl); + histos.fill(HIST("Trig_hist"), fSampleIndex, vz, multiplicity, triggerTrack.pt(), triggerTrack.invMass(), eventWeight * trigAmpl * trkeff); } else { - histos.fill(HIST("Trig_hist"), fSampleIndex, vz, multiplicity, triggerTrack.pt(), 1.0, eventWeight * trigAmpl); + histos.fill(HIST("Trig_hist"), fSampleIndex, vz, multiplicity, triggerTrack.pt(), 1.0, eventWeight * trigAmpl * trkeff); } } for (auto const& assoTrack : assocs) { auto assoAmpl = 1.0f; + + if (!isTrackSelected(assoTrack)) + continue; + if constexpr (requires { assoTrack.channelID(); }) { + if (cfgSel.cfgRequireFt0cOuterRing && !assoTrack.isTrackFT0Outer()) + continue; + if (cfgSel.cfgRequireFt0cInnerRing && assoTrack.isTrackFT0Outer()) + continue; assoAmpl = assoTrack.amplitude(); } else { assoAmpl = 1.0f; } - if (!isTrackSelected(assoTrack)) - continue; - float deltaPhi = RecoDecay::constrainAngle(triggerTrack.phi() - assoTrack.phi(), -PIHalf); float deltaEta = triggerTrack.eta() - assoTrack.eta(); if (!mixing) { - fillAssocTrackQA(assoTrack); - histos.fill(HIST("deltaEta_deltaPhi_same"), deltaPhi, deltaEta, eventWeight * trigAmpl * assoAmpl); + fillAssocTrackQA(assoTrack, assoAmpl); + histos.fill(HIST("deltaEta_deltaPhi_same"), deltaPhi, deltaEta, eventWeight * trigAmpl * assoAmpl * trkeff); } else { - histos.fill(HIST("deltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, eventWeight * trigAmpl * assoAmpl); + histos.fill(HIST("deltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, eventWeight * trigAmpl * assoAmpl * trkeff); } if constexpr (requires { triggerTrack.channelID(); }) { - target->getPairHist()->Fill(step, fSampleIndex, vz, multiplicity, 1.0, deltaPhi, deltaEta, 1.0, eventWeight * trigAmpl * assoAmpl); + target->getPairHist()->Fill(step, fSampleIndex, vz, multiplicity, 1.0, deltaPhi, deltaEta, 1.0, eventWeight * trigAmpl * assoAmpl * trkeff); } else if constexpr (requires { triggerTrack.invMass(); }) { - target->getPairHist()->Fill(step, fSampleIndex, vz, multiplicity, triggerTrack.pt(), deltaPhi, deltaEta, triggerTrack.invMass(), eventWeight * trigAmpl * assoAmpl); + target->getPairHist()->Fill(step, fSampleIndex, vz, multiplicity, triggerTrack.pt(), deltaPhi, deltaEta, triggerTrack.invMass(), eventWeight * trigAmpl * assoAmpl * trkeff); } else { - target->getPairHist()->Fill(step, fSampleIndex, vz, multiplicity, triggerTrack.pt(), deltaPhi, deltaEta, 1.0, eventWeight * trigAmpl * assoAmpl); + target->getPairHist()->Fill(step, fSampleIndex, vz, multiplicity, triggerTrack.pt(), deltaPhi, deltaEta, 1.0, eventWeight * trigAmpl * assoAmpl * trkeff); } } // associated tracks } // trigger tracks @@ -398,6 +500,7 @@ struct LongrangecorrDerived { if (std::abs(col.posZ()) >= cfgSel.cfgVtxCut) { return; } + loadEffCorrection(col.timestamp()); fillCollQA(col); auto multiplicity = 1.0f; if constexpr (requires { col.centrality(); }) { @@ -408,7 +511,11 @@ struct LongrangecorrDerived { } else { multiplicity = col.multiplicity(); } - fillCorrHist(same, triggers, assocs, false, col.posZ(), multiplicity, 1.0); + if (cfgSel.applyEffCorr) { + fillCorrHist(same, triggers, assocs, false, col.posZ(), multiplicity, 1.0); + } else { + fillCorrHist(same, triggers, assocs, false, col.posZ(), multiplicity, 1.0); + } } // process same template @@ -446,9 +553,23 @@ struct LongrangecorrDerived { continue; } } + if (std::abs(col1.posZ()) >= cfgSel.cfgVtxCut || std::abs(col2.posZ()) >= cfgSel.cfgVtxCut) { + continue; + } float eventweight = 1.0f / it.currentWindowNeighbours(); auto multiplicity = getMultiplicity(col1); - fillCorrHist(mixed, tracks1, tracks2, true, col1.posZ(), multiplicity, eventweight); + int bin = binningOnVtxAndMult.getBin(std::tuple(col1.posZ(), multiplicity)); + loadEffCorrection(col1.timestamp()); + + if (cfgSel.cfgVerbosity > 0) { + LOGF(info, "processMixed: Mixed collisions bin: %d pair: [%d, %d] %d (%.3f, %.3f), %d (%.3f, %.3f)", bin, it.isNewWindow(), it.currentWindowNeighbours(), col1.globalIndex(), col1.posZ(), col1.multiplicity(), col2.globalIndex(), col2.posZ(), col2.multiplicity()); + } + + if (cfgSel.applyEffCorr) { + fillCorrHist(mixed, tracks1, tracks2, true, col1.posZ(), multiplicity, eventweight); + } else { + fillCorrHist(mixed, tracks1, tracks2, true, col1.posZ(), multiplicity, eventweight); + } } // pair loop } // process mixed @@ -782,6 +903,87 @@ struct LongrangecorrDerived { processMcGenMixed(mccollisions, ft0as, ft0cs); } + using ColMCTrueTable = soa::Join; + using ColMCRecTable = soa::SmallGroups>; + using TrksMCRecTable = soa::Join; + Preslice perColMidtrack = aod::track::collisionId; + + template + bool isEventSelected(CheckCol const& col) + { + if (!col.sel8()) + return false; + if (!col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + return false; + if (!col.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + return false; + if (!col.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) + return false; + if (std::abs(col.posZ()) >= cfgSel.cfgVtxCut) + return false; + return true; + } + + template + bool isGenPartSelected(CheckGenPart const& particle) + { + if (!particle.isPhysicalPrimary() || !particle.producedByGenerator()) + return false; + auto pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (pdgParticle == nullptr) + return false; + if (std::abs(pdgParticle->Charge()) < KminCharge) + return false; + return true; + } + + void processTPCtrackEff(ColMCTrueTable::iterator const& mcCollision, ColMCRecTable const& RecCols, + TrksMCRecTable const& RecTracks, aod::McParticles const& mcparticles) + { + if (std::abs(mcCollision.posZ()) >= cfgSel.cfgVtxCut) { + return; + } + bool atLeastOne = false; + for (const auto& RecCol : RecCols) { + if (!isEventSelected(RecCol)) + continue; + if (RecCol.globalIndex() != mcCollision.bestCollisionIndex()) + continue; + auto recTracksPart = RecTracks.sliceBy(perColMidtrack, RecCol.globalIndex()); + atLeastOne = true; + } + for (const auto& particle : mcparticles) { + if (!isGenPartSelected(particle) || + std::abs(particle.eta()) > cfgSel.cfgEtaCut || + particle.pt() < cfgSel.cfgPtCutMin || + particle.pt() > cfgSel.cfgPtCutMax) + continue; + if (atLeastOne) + histos.fill(HIST("hGenMCdndpt"), mcCollision.posZ(), particle.eta(), particle.pt()); + } + for (const auto& RecCol : RecCols) { + if (!isEventSelected(RecCol)) + continue; + if (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()) { + histos.fill(HIST("hRecMCdndpt"), mcCollision.posZ(), particle.eta(), particle.pt()); + } + } + } + } + PROCESS_SWITCH(LongrangecorrDerived, processTpcft0aSE, "same event TPC vs FT0A", false); PROCESS_SWITCH(LongrangecorrDerived, processTpcft0aME, "mixed event TPC vs FT0A", false); PROCESS_SWITCH(LongrangecorrDerived, processTpcft0cSE, "same event TPC vs FT0C", false); @@ -828,6 +1030,7 @@ struct LongrangecorrDerived { PROCESS_SWITCH(LongrangecorrDerived, processMcGenMftft0aME, "mixed MC gen event MFT vs FT0A", false); PROCESS_SWITCH(LongrangecorrDerived, processMcGenFt0aft0cSE, "same MC gen event FT0A vs FT0C", false); PROCESS_SWITCH(LongrangecorrDerived, processMcGenFt0aft0cME, "mixed MC gen event FT0A vs FT0C", false); + PROCESS_SWITCH(LongrangecorrDerived, processTPCtrackEff, "process TPC track efficiency", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From aaf414f9f711922b75f634af9b604e9e65c46b47 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Sun, 14 Jun 2026 17:36:44 +0000 Subject: [PATCH 4/4] Please consider the following formatting changes --- .../Tasks/longrangecorrDerived.cxx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx b/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx index b89a9885108..a1797d0aa84 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx @@ -432,10 +432,10 @@ struct LongrangecorrDerived { } if constexpr (requires { triggerTrack.channelID(); }) { - if (cfgSel.cfgRequireFt0aOuterRing && !triggerTrack.isTrackFT0Outer()) - continue; - if (cfgSel.cfgRequireFt0aInnerRing && triggerTrack.isTrackFT0Outer()) - continue; + if (cfgSel.cfgRequireFt0aOuterRing && !triggerTrack.isTrackFT0Outer()) + continue; + if (cfgSel.cfgRequireFt0aInnerRing && triggerTrack.isTrackFT0Outer()) + continue; trigAmpl = triggerTrack.amplitude(); } else { trigAmpl = 1.0; @@ -466,10 +466,10 @@ struct LongrangecorrDerived { continue; if constexpr (requires { assoTrack.channelID(); }) { - if (cfgSel.cfgRequireFt0cOuterRing && !assoTrack.isTrackFT0Outer()) - continue; - if (cfgSel.cfgRequireFt0cInnerRing && assoTrack.isTrackFT0Outer()) - continue; + if (cfgSel.cfgRequireFt0cOuterRing && !assoTrack.isTrackFT0Outer()) + continue; + if (cfgSel.cfgRequireFt0cInnerRing && assoTrack.isTrackFT0Outer()) + continue; assoAmpl = assoTrack.amplitude(); } else { assoAmpl = 1.0f;