diff --git a/PWGLF/Tasks/GlobalEventProperties/PseudorapidityDensityMFT.cxx b/PWGLF/Tasks/GlobalEventProperties/PseudorapidityDensityMFT.cxx index 50ec3c8889e..83d6ef873c2 100644 --- a/PWGLF/Tasks/GlobalEventProperties/PseudorapidityDensityMFT.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/PseudorapidityDensityMFT.cxx @@ -10,8 +10,8 @@ // or submit itself to any jurisdiction. /// \file PseudorapidityDensityMFT.cxx -/// \author Tulika Tripathy /// \author Sarah Herrmann +/// \author Tulika Tripathy /// \brief This code loops over MFT tracks and collisions and fills histograms /// useful to compute dNdeta @@ -72,31 +72,31 @@ using namespace o2::aod::rctsel; const AxisSpec ptAxis = {2001, -0.005, 20.005}; const AxisSpec deltazAxis = {6100, -6.1, 6.1}; const AxisSpec zAxis = {3001, -30.1, 30.1}; -const AxisSpec phiAxis = {629, 0, o2::constants::math::TwoPI, "Rad", "phi axis"}; // do not change -const AxisSpec etaAxis = {18, -4.6, -1.}; // do not change -// const AxisSpec dcaXyAxis = {2000, -10, 10}; -// const AxisSpec dcaZAxis = {2000, -10, 10}; -// const AxisSpec dcaXAxis = {2000, -10, 10}; -// const AxisSpec dcaYAxis = {2000, -10, 10};// previous AxisSpec dcaYAxis = {2000, -10, 10}; +const AxisSpec phiAxis = {629, 0, o2::constants::math::TwoPI, "Rad", "phi axis"}; +const AxisSpec etaAxis = {18, -4.6, -1.}; +// AxisSpec dcaXyAxis = {2000, -10, 10}; +// AxisSpec dcaZAxis = {2000, -10, 10}; +// AxisSpec dcaXAxis = {2000, -10, 10}; +// AxisSpec dcaYAxis = {2000, -10, 10};// previous AxisSpec dcaYAxis = {2000, -10, 10}; const AxisSpec dcaXyAxis = {6000, -30, 30}; const AxisSpec dcaZAxis = {6000, -30, 30}; const AxisSpec dcaXAxis = {6000, -30, 30}; const AxisSpec dcaYAxis = {6000, -30, 30}; // previous AxisSpec dcaYAxis = {2000, -10, 10}; -// const AxisSpec dcaXyAxis = {600, -0.15f, 0.15f}; -// const AxisSpec dcaZAxis = {600, -0.15f, 0.15f}; -// const AxisSpec dcaXAxis = {600, -0.15f, 0.15f}; -// const AxisSpec dcaYAxis = {600, -0.15f, 0.15f}; +// AxisSpec dcaXyAxis = {600, -0.15f, 0.15f}; +// AxisSpec dcaZAxis = {600, -0.15f, 0.15f}; +// AxisSpec dcaXAxis = {600, -0.15f, 0.15f}; +// AxisSpec dcaYAxis = {600, -0.15f, 0.15f}; // bin width 0.0005 cm: range [-30, 30] cm => 60/0.0005 = 120000 bins // Keep bin width = 0.0005 cm (5 um): range [-1, 1] cm => 2.0/0.0005 = 4000 bins -// const AxisSpec axisBinsDCA = {600, -0.15f, 0.15f, "#it{dca}_{xy} (cm)"}; +// AxisSpec axisBinsDCA = {600, -0.15f, 0.15f, "#it{dca}_{xy} (cm)"}; const AxisSpec centAxis = {{0, 10, 20, 30, 40, 50, 60, 70, 80, 100}}; // Vertex position axes (cm) const AxisSpec vxAxis = {200, -0.5, 0.5, "V_{x} (cm)"}; const AxisSpec vyAxis = {200, -0.5, 0.5, "V_{y} (cm)"}; // Status axis for reco/truth (1=reco, 2=true) -const AxisSpec recoTruthStatusAxis = {2, 0.5, 2.5, "status"}; +AxisSpec recoTruthStatusAxis = {2, 0.5, 2.5, "status"}; // Delta-vertex axes (reco - true) in cm const AxisSpec deltaVxAxis = {400, -0.5, 0.5, "#DeltaV_{x} = V_{x}^{rec}-V_{x}^{true} (cm)"}; @@ -154,7 +154,6 @@ struct PseudorapidityDensityMFT { Preslice perColCentral = aod::track::collisionId; Service pdg{}; - // --- CCDB magnetic field (needed for propagateToDCAhelix in this device) --- Service ccdbMgr{}; Configurable ccdburlMag{"ccdburlMag", "http://alice-ccdb.cern.ch", @@ -295,6 +294,7 @@ struct PseudorapidityDensityMFT { } static constexpr int NoCompatibleCollisions = 0; static constexpr int SingleCompatibleCollision = 1; + static constexpr int ChargeUnitTimesThree = 3; void initMagField(FullBCs::iterator const& bc) @@ -505,7 +505,7 @@ struct PseudorapidityDensityMFT { auto* x = h->GetXaxis(); x->SetBinLabel(static_cast(GenRecoCutBin::AllRecoCollisions), "All reco collisions (loop entry)"); x->SetBinLabel(static_cast(GenRecoCutBin::RctMFT), "myChecker (cfg)"); - x->SetBinLabel(static_cast(GenRecoCutBin::UseGoodItsLayersAll), "kIsGoodItsLayersAll"); + x->SetBinLabel(static_cast(GenRecoCutBin::UseGoodItsLayersAll), "kIsGoodITSLayersAll"); x->SetBinLabel(static_cast(GenRecoCutBin::UseContBestCollisionIndex), "useContBestcollisionIndex"); x->SetBinLabel(static_cast(GenRecoCutBin::HasMcCollision), "has_mcCollision()"); x->SetBinLabel(static_cast(GenRecoCutBin::VzWindow), "Vz window"); @@ -643,24 +643,9 @@ struct PseudorapidityDensityMFT { registry.add({"Purity/DCAyVsDCAx_Right", ";DCA_{x} (cm);DCA_{y} (cm)", {HistType::kTH2F, {dcaXAxis, dcaYAxis}}}); - registry.add({"Purity/reco/woOrp/All", - ";bin;counts", - {HistType::kTH1F, {{1, 0.5, 1.5}}}}); - registry.add({"Purity/reco/woOrp/AllEta", - ";#eta;counts", - {HistType::kTH1F, {etaBinning}}}); - registry.add({"Purity/SelectedAfterDCAxy/PrimaryAll", - ";bin;counts", - {HistType::kTH1F, {{1, 0.5, 1.5}}}}); - registry.add({"Purity/SelectedAfterDCAxy/PrimaryAllEta", - ";#eta;counts", - {HistType::kTH1F, {etaBinning}}}); registry.add({"TracksToPartPhiEta", "; #varphi; #eta; tracks", {HistType::kTH2F, {phiAxis, etaBinning}}}); - registry.add({"EventsReco", - "; status; events", - {HistType::kTH1F, {{7, 0.5, 7.5}}}}); // Additional histograms for processGenReco (w/o orphan), grouped under Purity/reco/ registry.add({"Purity/reco/weakStrange/SelectedTracksEta", @@ -669,9 +654,38 @@ struct PseudorapidityDensityMFT { registry.add({"Purity/reco/weakStrange/SelectedTracksEtaZvtx", "; #eta; #it{z}_{vtx} (cm); selected reco tracks from weak strange decays", {HistType::kTH2F, {etaBinning, zAxis}}}); - registry.add({"Purity/reco/SelectedTracksEta", - "; #eta; selected reco tracks", - {HistType::kTH1F, {etaBinning}}}); + // Selected non-fake secondary tracks with a recognised immediate + // strange mother. Parent species: 1 = K0S, 2 = Lambda, 3 = anti-Lambda. + registry.add({"Strangeness/Fwd/RecoStrangeEtaZvtx", + ";#eta_{reco};z_{reco} (cm);DCA_{xy} (cm);DCA_{z} (cm);parent species", + {HistType::kTHnSparseF, + {etaBinning, zAxis, dcaXyAxis, dcaZAxis, {3, 0.5, 3.5}}}}); + { + auto histogram = registry.get(HIST("Strangeness/Fwd/RecoStrangeEtaZvtx")); + auto* parentAxis = histogram->GetAxis(4); + parentAxis->SetBinLabel(1, "K0S"); + parentAxis->SetBinLabel(2, "Lambda"); + parentAxis->SetBinLabel(3, "anti-Lambda"); + } + // Central eta has its own axis: the MFT eta binning is forward-only. + const AxisSpec midEtaAxis = { + 200, -static_cast(estimatorEta.value), + static_cast(estimatorEta.value)}; + registry.add({"Strangeness/Mid/RecoAllEtaZvtx", + ";#eta_{reco};z_{reco} (cm);DCA_{xy} (cm);DCA_{z} (cm)", + {HistType::kTHnSparseF, + {midEtaAxis, zAxis, dcaXyAxis, dcaZAxis}}}); + registry.add({"Strangeness/Mid/RecoStrangeEtaZvtx", + ";#eta_{reco};z_{reco} (cm);DCA_{xy} (cm);DCA_{z} (cm);parent species", + {HistType::kTHnSparseF, + {midEtaAxis, zAxis, dcaXyAxis, dcaZAxis, {3, 0.5, 3.5}}}}); + { + auto histogram = registry.get(HIST("Strangeness/Mid/RecoStrangeEtaZvtx")); + auto* parentAxis = histogram->GetAxis(4); + parentAxis->SetBinLabel(1, "K0S"); + parentAxis->SetBinLabel(2, "Lambda"); + parentAxis->SetBinLabel(3, "anti-Lambda"); + } registry.add({"Purity/reco/woOrp/nTrk", " ; N_{Trk}^{all}", {HistType::kTH1F, {{701, -0.5, 700.5}}}}); @@ -797,33 +811,6 @@ struct PseudorapidityDensityMFT { registry.add({"Purity/mc/PrimaryTracksPhiEta", "; #varphi; #eta; tracks", {HistType::kTH2F, {phiAxis, etaBinning}}}); - // --- MC-side (NO-DCA) truth histograms for pre-DCA accounting --- - registry.add({"Purity/mc_noDCA/PrimaryAll", - ";bin;counts", - {HistType::kTH1F, {{1, 0.5, 1.5}}}}); - registry.add({"Purity/mc_noDCA/PrimaryAllEta", - ";#eta;counts", - {HistType::kTH1F, {etaBinning}}}); - registry.add({"Purity/mc_noDCA/PrimaryTracksEtaZvtx", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {etaBinning, zAxis}}}); - registry.add({"Purity/mc_noDCA/PrimaryTracksEtaZvtx_gt0", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {etaBinning, zAxis}}}); - registry.add({"Purity/mc_noDCA/PrimaryTracksPtZvtx_gt0", - "; p_{T} (GeV/c); #it{z}_{vtx} (cm); primary tracks", - {HistType::kTH2F, {ptAxis, zAxis}}}); - registry.add({"Purity/mc_noDCA/PrimaryTracksPhiEta", - "; #varphi; #eta; tracks", - {HistType::kTH2F, {phiAxis, etaBinning}}}); - - // Book keeping for pre-DCA selection counters (for symmetry with AfterDCAxy) - registry.add({"Purity/SelectedBeforeDCAxy/PrimaryAll", - ";bin;counts", - {HistType::kTH1F, {{1, 0.5, 1.5}}}}); - registry.add({"Purity/SelectedBeforeDCAxy/PrimaryAllEta", - ";#eta;counts", - {HistType::kTH1F, {etaBinning}}}); // --- Fake-track counters (reco side after DCA selections) --- registry.add({"Purity/Fakes/All", ";bin;counts", @@ -839,13 +826,6 @@ struct PseudorapidityDensityMFT { {HistType::kTH2F, {phiAxis, etaBinning}}}); // Fake reason breakdown: 1-INEL>0 true (vz), 2-Reco sel (woOrp), 3-has_mcParticle, 4-isPrimary, 5-rightVertex - // --- Purity calculation histograms (as profiles: purity = ) --- - registry.add({"Purity/PurityOverall", - ";bin;purity", - {HistType::kTProfile, {{1, 0.5, 1.5}}}}); - registry.add({"Purity/PurityVsEta", - ";#eta;purity", - {HistType::kTProfile, {etaBinning}}}); registry.add({"RightWrong", ";category;counts", {HistType::kTH1F, {{4, 0.5, 4.5}}}}); @@ -966,6 +946,14 @@ struct PseudorapidityDensityMFT { {HistType::kTHnSparseF, {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + // Matched reconstructed physical primaries after all event and track + // selections, binned in generated eta for an efficiency-vs-eta + // numerator without reconstructed-eta migration. + registry.add({"Purity/RecoSparsePrimaryTruthEta", + ";#eta_{true};DCA_{xy}^{reco} (cm);DCA_{z}^{reco} (cm)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis}}}); + registry.add({"Purity/RecoSparseSecondary", ";#eta;DCA_{xy} (cm);DCA_{z} (cm);DCA_{x} (cm);DCA_{y} (cm)", {HistType::kTHnSparseF, @@ -1111,6 +1099,9 @@ struct PseudorapidityDensityMFT { registry.add({"TracksEtaZvtxGen_gt0_primary", "; #eta; #it{z}_{vtx} (cm); primary tracks", {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"TracksEtaZvtxGen_gt0t_primary", + "; #eta; #it{z}_{vtx} (cm); primary tracks from true INEL>0 events", + {HistType::kTH2F, {etaBinning, zAxis}}}); registry.add({"TracksPhiEtaGen_gt0_primary", "; #varphi; #eta; primary tracks", {HistType::kTH2F, {phiAxis, etaBinning}}}); @@ -1503,6 +1494,12 @@ struct PseudorapidityDensityMFT { soa::Join>; // central tracks for INEL>0 + // MC-only input for the central contamination study. Keep FiCentralTracks + // unchanged so data and reconstructed INEL>0 selections are unaffected. + using CentralTracksMC = soa::Join< + aod::Tracks, aod::TracksExtra, aod::TrackSelection, + aod::TracksDCA, aod::McTrackLabels>; + void processMult(CollwEv::iterator const& collision, aod::MFTTracks const& tracks, FiCentralTracks const& midtracks, aod::Tracks const&) @@ -1601,8 +1598,6 @@ struct PseudorapidityDensityMFT { const bool hasMidtracks = midtracks.size() > 0; if (midtracks.size() > 0) { // registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::Sel8VzInelGt0)); - registry.fill(HIST("EventsNtrkZvtx_gt0"), nTrk, z); - registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_sel8_inelgt0"), nTrk, z); eventsInel.insert(collision.globalIndex()); } if (usePerCollisionSampleGt0Cut && !hasPerCollisionSample) { @@ -1654,6 +1649,14 @@ struct PseudorapidityDensityMFT { return; } + // Selected reconstructed INEL>0 events. Keep this event population aligned + // with Tracks/2Danalysis/EtaZvtx_sel8_inelgt0, which is filled below only + // for events with selected central-barrel tracks. + if (hasMidtracks) { + registry.fill(HIST("EventsNtrkZvtx_gt0"), nTrk, z); + registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_sel8_inelgt0"), nTrk, z); + } + // registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::VzItsRof)); // registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::VzSelected)); registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_sel8"), nTrk, z); @@ -1682,11 +1685,11 @@ struct PseudorapidityDensityMFT { ((phi <= PhiVetoLow) || ((phi >= PhiVetoPiMin) && (phi <= PhiVetoPiMax)) || (phi >= PhiVetoHigh))) || - (useDCAxyCut && dcaXyCut > maxDCAxy) || (usePtCut && ptCut > cfgnPt); + (useDCAxyCut && std::abs(dcaXyCut) > maxDCAxy) || (usePtCut && ptCut > cfgnPt); if constexpr (std::is_same_v>) { const float dcaZCut = retrack.bestDCAZ(); - failTrackCuts = failTrackCuts || (useDCAzCut && dcaZCut > maxDCAz); + failTrackCuts = failTrackCuts || (useDCAzCut && std::abs(dcaZCut) > maxDCAz); } if (failTrackCuts) { @@ -2203,7 +2206,7 @@ struct PseudorapidityDensityMFT { const auto countAndPassEvSelGenReco = [&](auto const& collision) { struct EvSelStep { bool enabled{false}; - decltype(aod::evsel::kIsTriggerTVX) bit{}; + decltype(aod::evsel::kIsTriggerTVX) bit; GenRecoCutBin bin{GenRecoCutBin::AllRecoCollisions}; }; @@ -2463,15 +2466,16 @@ struct PseudorapidityDensityMFT { o2::soa::SmallGroups> const& collisions, FullBCs const& bcs, MFTTracksLabeledOrg const& originalTracks, MFTTracksT const& tracks, - FiCentralTracks const& midtracks, aod::McParticles const& mcParticles, /*ParticlesGen const& particlesgen,*/ + FiCentralTracks const& midtracks, + CentralTracksMC const& centralTracksMC, + aod::McParticles const& mcParticles, /*ParticlesGen const& particlesgen,*/ bool useOriginalPropagatedDcaZ = false) { - bool onlyVz = false; // EtaZvtxGen_t - bool onlyVzGt0 = false; // EtaZvtxGen_gt0t - bool atLeastOneSel8Vz = false; // EtaZvtxGen bool atLeastOneSel8VzGt0 = false; // EtaZvtxGen_gt0 bool hasRecoCollisionForPNch{false}; + int64_t selectedRecoNtrkForEventLoss{0}; + float selectedRecoZvtxForEventLoss{0.f}; const auto fillGenRecoCut = [&](GenRecoCutBin bin) { registry.fill(HIST("EventsRecoCuts_GenReco"), static_cast(bin)); @@ -2507,10 +2511,29 @@ struct PseudorapidityDensityMFT { LOGF(fatal, "BC table is empty: cannot initialize magnetic field"); } + // Classify the generated event before filling the reconstructed-primary + // efficiency numerator. This is the same true-INEL>0 definition used + // below for TracksEtaZvtxGen_gt0_primary. + auto perCollisionMCSampleCentral = mcSampleCentralGenReco->sliceByCached( + aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); + int nChargedCentral = 0; + for (const auto& particle : perCollisionMCSampleCentral) { + auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (!pdgParticle || + std::abs(pdgParticle->Charge()) < ChargeUnitTimesThree || + !particle.isPhysicalPrimary()) { + continue; + } + ++nChargedCentral; + } + const bool isTrueINELgt0ForEfficiency = + nChargedCentral > 0 && + mcCollision.posZ() >= cfgVzCut1 && mcCollision.posZ() <= cfgVzCut2; + const auto countAndPassEvSelGenReco = [&](auto const& collision) { struct EvSelStep { bool enabled{false}; - decltype(aod::evsel::kIsTriggerTVX) bit{}; + decltype(aod::evsel::kIsTriggerTVX) bit; GenRecoCutBin bin{GenRecoCutBin::AllRecoCollisions}; }; @@ -2570,38 +2593,16 @@ struct PseudorapidityDensityMFT { } fillGenRecoCut(GenRecoCutBin::UseContBestCollisionIndex); - const bool passSel8Like = - (!useEvSel) || - ((!useTriggerTVX || collision.selection_bit(aod::evsel::kIsTriggerTVX)) && - (!useNoTimeFrameBorderCut || collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) && - (!useNoITSROFrameBorderCut || collision.selection_bit(aod::evsel::kNoITSROFrameBorder))); - auto perCollisionSample = originalTracks.sliceBy( perCol, collision.globalIndex()); const auto z = collision.posZ(); - if (passSel8Like) { - if ((z >= cfgVzCut1) && (z <= cfgVzCut2)) { - atLeastOneSel8Vz = true; - } - } - if ((z >= cfgVzCut1) && (z <= cfgVzCut2)) { - onlyVz = true; - } if ((z < cfgVzCut1) || (z > cfgVzCut2)) { continue; } fillGenRecoCut(GenRecoCutBin::VzWindow); auto perCollisionSampleCentral = midtracks.sliceBy(perColCentral, collision.globalIndex()); - if (perCollisionSampleCentral.size() > 0) { - onlyVzGt0 = true; - } - if (passSel8Like && perCollisionSampleCentral.size() > 0) { - atLeastOneSel8VzGt0 = true; - registry.fill(HIST("EventsNtrkZvtxGen_gt0"), - perCollisionSample.size(), collision.posZ()); - } registry.fill(HIST("EventsZposDiff"), collision.posZ() - mcCollision.posZ()); if (useZDiffCut) { @@ -2620,6 +2621,54 @@ struct PseudorapidityDensityMFT { continue; } + // The reconstructed event has now passed the z window, reconstructed + // INEL>0, reco-gen z matching and the complete event selection. + if (!atLeastOneSel8VzGt0) { + selectedRecoNtrkForEventLoss = static_cast(perCollisionSample.size()); + selectedRecoZvtxForEventLoss = collision.posZ(); + } + atLeastOneSel8VzGt0 = true; + + // Diagnostic-only central study for this accepted reconstructed event. + // Match the existing INEL>0 central track filter explicitly; none of + // these track-level continues rejects the event or changes MFT fills. + auto centralTracksForStudy = centralTracksMC.sliceBy( + perColCentral, collision.globalIndex()); + for (const auto& centralTrack : centralTracksForStudy) { + const auto flags = centralTrack.trackCutFlag(); + const bool hasTpc = + (centralTrack.detectorMap() & static_cast(aod::track::TPC)) != 0; + if ((flags & TrackSelectionIts) != TrackSelectionIts || + (hasTpc && (flags & TrackSelectionTpc) != TrackSelectionTpc) || + (flags & TrackSelectionDca) != TrackSelectionDca || + std::abs(centralTrack.eta()) >= estimatorEta) { + continue; + } + + // Inclusive denominator: include fake and unlabelled selected tracks. + registry.fill(HIST("Strangeness/Mid/RecoAllEtaZvtx"), + centralTrack.eta(), z, + centralTrack.dcaXY(), centralTrack.dcaZ()); + if (!centralTrack.has_mcParticle() || centralTrack.mcMask() != 0) { + continue; + } + const auto particle = centralTrack.template mcParticle_as(); + if (particle.isPhysicalPrimary() || !particle.has_mothers()) { + continue; + } + // Same immediate-mother species definition as the forward template. + const auto mother = particle.template mothers_as().front(); + const int parentPdg = mother.pdgCode(); + if (parentPdg != PDG_t::kK0Short && + std::abs(parentPdg) != PDG_t::kLambda0) { + continue; + } + const int parentSpecies = parentPdg == PDG_t::kK0Short ? 1 : (parentPdg == PDG_t::kLambda0 ? 2 : 3); + registry.fill(HIST("Strangeness/Mid/RecoStrangeEtaZvtx"), + centralTrack.eta(), z, + centralTrack.dcaXY(), centralTrack.dcaZ(), parentSpecies); + } + const int recoCol = collision.globalIndex(); const int mcCol = collision.mcCollisionId(); @@ -2756,6 +2805,17 @@ struct PseudorapidityDensityMFT { ++nRecoMFTSelectedForPNch; + // Inclusive reconstructed-MC denominator: fill every selected track, + // including tracks without an MC-particle label. + registry.fill(HIST("Purity/reco/woOrp/woOrpTracksEtaZvtx"), originalTrack.eta(), z); + registry.fill(HIST("Purity/reco/woOrp/woOrpTracksPtZvtx"), originalTrack.pt(), z); + registry.fill(HIST("Purity/reco/woOrp/woOrpEtaZvtx_gt0"), originalTrack.eta(), z); + registry.fill(HIST("Purity/reco/woOrp/woOrpPtZvtx_gt0"), originalTrack.pt(), z); + registry.fill(HIST("Purity/reco/woOrp/woOrpTracksDCAxyZvtx_gt0"), dcaXyCut, z); + registry.fill(HIST("Purity/reco/woOrp/woOrpTracksDCAzZvtx_gt0"), dcaZCut, z); + registry.fill(HIST("Purity/reco/woOrp/woOrpTracksPhiEta"), phi, originalTrack.eta()); + ++woOrpCount; + const bool hasMcLabel = track.has_mcParticle(); const bool isFakeByLabel = hasMcLabel ? (track.mcMask() != 0) : false; const bool isTrueByLabel = hasMcLabel && !isFakeByLabel; @@ -2812,6 +2872,14 @@ struct PseudorapidityDensityMFT { std::abs(mcpartMother.pdgCode()) == PDG_t::kLambda0) { registry.fill(HIST("Purity/reco/weakStrange/SelectedTracksEta"), originalTrack.eta()); registry.fill(HIST("Purity/reco/weakStrange/SelectedTracksEtaZvtx"), originalTrack.eta(), z); + // Keep the legacy histograms unchanged; the new SEF template + // excludes fake labels and counts only matched secondaries. + if (isSecondaryCharged) { + const int parentSpecies = + mcpartMother.pdgCode() == PDG_t::kK0Short ? 1 : (mcpartMother.pdgCode() == PDG_t::kLambda0 ? 2 : 3); + registry.fill(HIST("Strangeness/Fwd/RecoStrangeEtaZvtx"), + etaReco, z, dcaXYReco, dcaZReco, parentSpecies); + } } } } @@ -2962,6 +3030,10 @@ struct PseudorapidityDensityMFT { if (isPrimaryCharged) { registry.fill(HIST("Purity/RecoSparsePrimary"), etaReco, dcaXYReco, dcaZReco, dcaXReco, dcaYReco); + if (isTrueINELgt0ForEfficiency) { + registry.fill(HIST("Purity/RecoSparsePrimaryTruthEta"), + track.mcParticle().eta(), dcaXYReco, dcaZReco); + } } else { registry.fill(HIST("Purity/RecoSparseSecondary"), etaReco, dcaXYReco, dcaZReco, dcaXReco, dcaYReco); @@ -3012,14 +3084,6 @@ struct PseudorapidityDensityMFT { etaTruth, dcaXYtruth, dcaZtruth, dcaXtruth, dcaYtruth); } - registry.fill(HIST("Purity/reco/woOrp/woOrpTracksEtaZvtx"), originalTrack.eta(), z); - registry.fill(HIST("Purity/reco/woOrp/woOrpTracksPtZvtx"), originalTrack.pt(), z); - registry.fill(HIST("Purity/reco/woOrp/woOrpEtaZvtx_gt0"), originalTrack.eta(), z); - registry.fill(HIST("Purity/reco/woOrp/woOrpPtZvtx_gt0"), originalTrack.pt(), z); - registry.fill(HIST("Purity/reco/woOrp/woOrpTracksDCAxyZvtx_gt0"), dcaXyCut, z); - registry.fill(HIST("Purity/reco/woOrp/woOrpTracksDCAzZvtx_gt0"), dcaZCut, z); - registry.fill(HIST("Purity/reco/woOrp/woOrpTracksPhiEta"), phi, originalTrack.eta()); - if (isFakeByLabel) { registry.fill(HIST("Purity/reco/woOrp_fake/woOrpTracksEtaZvtx"), originalTrack.eta(), z); registry.fill(HIST("Purity/reco/woOrp_fake/woOrpTracksPtZvtx"), originalTrack.pt(), z); @@ -3049,8 +3113,6 @@ struct PseudorapidityDensityMFT { registry.fill(HIST("Purity/reco/woOrp_primary/woOrpPtZvtx_gt0"), originalTrack.pt(), z); } - ++woOrpCount; - const float xTrue = mcColObj.posX(); const float yTrue = mcColObj.posY(); const float zTrue = mcColObj.posZ(); @@ -3169,16 +3231,6 @@ struct PseudorapidityDensityMFT { } } - registry.fill(HIST("Purity/SelectedAfterDCAxy/PrimaryAll"), static_cast(SingleCountBin::Count)); - registry.fill(HIST("Purity/SelectedAfterDCAxy/PrimaryAllEta"), mcPart.eta()); - - registry.fill(HIST("Purity/PurityOverall"), - static_cast(SingleCountBin::Count), - isPrimaryCharged ? static_cast(BoolBin::Yes) - : static_cast(BoolBin::No)); - registry.fill(HIST("Purity/PurityVsEta"), originalTrack.eta(), - isPrimaryCharged ? static_cast(BoolBin::Yes) - : static_cast(BoolBin::No)); } // hasmclable } // track loop } // track>mid @@ -3204,25 +3256,16 @@ struct PseudorapidityDensityMFT { } registry.fill(HIST("EventsNtrkZvtxGen_t"), nCharged, mcCollision.posZ()); } - auto perCollisionMCSampleCentral = mcSampleCentralGenReco->sliceByCached( - aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); - auto nChargedCentral = 0; - for (const auto& particle : perCollisionMCSampleCentral) { - auto charge = 0.; - auto p = pdg->GetParticle(particle.pdgCode()); - if (p != nullptr) { - charge = p->Charge(); - } - if (std::abs(charge) < ChargeUnitTimesThree) { - continue; - } - nChargedCentral++; - } if ((mcCollision.posZ() >= cfgVzCut1) && (mcCollision.posZ() <= cfgVzCut2)) { if (nChargedCentral > 0) { registry.fill(HIST("EventEfficiencymc"), static_cast(EventEfficiencyBin::GeneratedInelGt0)); registry.fill(HIST("EventsNtrkZvtxGen_gt0t"), nCharged, mcCollision.posZ()); + if (atLeastOneSel8VzGt0) { + registry.fill(HIST("EventsNtrkZvtxGen_gt0"), + selectedRecoNtrkForEventLoss, + selectedRecoZvtxForEventLoss); + } } } @@ -3255,42 +3298,46 @@ struct PseudorapidityDensityMFT { } } if (cfgnEta1 < particle.eta() && particle.eta() < cfgnEta2 && (phi > cfgPhiCut1 && phi < cfgPhiCut2)) { - if (onlyVz) { + if (mcCollision.posZ() >= cfgVzCut1 && mcCollision.posZ() <= cfgVzCut2) { registry.fill(HIST("TracksEtaZvtxGen_t"), particle.eta(), mcCollision.posZ()); registry.fill(HIST("TracksPtEtaGen_t"), particle.pt(), particle.eta()); } - if (onlyVzGt0) { + if (mcCollision.posZ() >= cfgVzCut1 && mcCollision.posZ() <= cfgVzCut2) { registry.fill(HIST("TracksEtaZvtxGen_gt0t"), particle.eta(), mcCollision.posZ()); registry.fill(HIST("TracksPhiEtaGen_gt0t"), particle.phi(), particle.eta()); - } - if (atLeastOneSel8Vz) { - registry.fill(HIST("TracksEtaZvtxGen"), particle.eta(), - mcCollision.posZ()); - registry.fill(HIST("TracksPtEtaGen"), particle.pt(), particle.eta()); - registry.fill(HIST("TracksPhiEtaGen"), particle.phi(), particle.eta()); - registry.fill(HIST("TracksPhiZvtxGen"), particle.phi(), - mcCollision.posZ()); - if (particle.isPhysicalPrimary()) { - registry.fill(HIST("Purity/mc/PrimaryAll"), static_cast(SingleCountBin::Count)); - registry.fill(HIST("Purity/mc/PrimaryAllEta"), particle.eta()); - registry.fill(HIST("Purity/mc/PrimaryTracksEtaZvtx"), particle.eta(), mcCollision.posZ()); - registry.fill(HIST("Purity/mc/PrimaryTracksPhiEta"), particle.phi(), particle.eta()); - } - if (atLeastOneSel8VzGt0) { - registry.fill(HIST("TracksEtaZvtxGen_gt0"), particle.eta(), + if (nChargedCentral > 0) { + if (particle.isPhysicalPrimary()) { + registry.fill(HIST("TracksEtaZvtxGen_gt0t_primary"), particle.eta(), mcCollision.posZ()); + } + registry.fill(HIST("TracksEtaZvtxGen"), particle.eta(), + mcCollision.posZ()); + registry.fill(HIST("TracksPtEtaGen"), particle.pt(), particle.eta()); + registry.fill(HIST("TracksPhiEtaGen"), particle.phi(), particle.eta()); + registry.fill(HIST("TracksPhiZvtxGen"), particle.phi(), mcCollision.posZ()); - registry.fill(HIST("TracksPhiEtaGen_gt0"), particle.phi(), particle.eta()); if (particle.isPhysicalPrimary()) { - registry.fill(HIST("TracksEtaZvtxGen_gt0_primary"), particle.eta(), mcCollision.posZ()); - registry.fill(HIST("TracksPhiEtaGen_gt0_primary"), particle.phi(), particle.eta()); - registry.fill(HIST("TracksPtZvtxGen_gt0_primary"), particle.pt(), mcCollision.posZ()); - registry.fill(HIST("Purity/mc/PrimaryTracksEtaZvtx_gt0"), particle.eta(), mcCollision.posZ()); - registry.fill(HIST("Purity/mc/PrimaryTracksPtZvtx_gt0"), particle.pt(), mcCollision.posZ()); - // registry.fill(HIST("Purity/mc/PrimaryTracksDCAxyZvtx_gt0"), dcaXyCut, mcCollision.posZ()); - // registry.fill(HIST("Purity/mc/PrimaryTracksDCAzZvtx_gt0"), dcaZCut, mcCollision.posZ()); + registry.fill(HIST("Purity/mc/PrimaryAll"), static_cast(SingleCountBin::Count)); + registry.fill(HIST("Purity/mc/PrimaryAllEta"), particle.eta()); + registry.fill(HIST("Purity/mc/PrimaryTracksEtaZvtx"), particle.eta(), mcCollision.posZ()); + registry.fill(HIST("Purity/mc/PrimaryTracksPhiEta"), particle.phi(), particle.eta()); + } + + if (atLeastOneSel8VzGt0) { + registry.fill(HIST("TracksEtaZvtxGen_gt0"), particle.eta(), + mcCollision.posZ()); + registry.fill(HIST("TracksPhiEtaGen_gt0"), particle.phi(), particle.eta()); + if (particle.isPhysicalPrimary()) { + registry.fill(HIST("TracksEtaZvtxGen_gt0_primary"), particle.eta(), mcCollision.posZ()); + registry.fill(HIST("TracksPhiEtaGen_gt0_primary"), particle.phi(), particle.eta()); + registry.fill(HIST("TracksPtZvtxGen_gt0_primary"), particle.pt(), mcCollision.posZ()); + registry.fill(HIST("Purity/mc/PrimaryTracksEtaZvtx_gt0"), particle.eta(), mcCollision.posZ()); + registry.fill(HIST("Purity/mc/PrimaryTracksPtZvtx_gt0"), particle.pt(), mcCollision.posZ()); + // registry.fill(HIST("Purity/mc/PrimaryTracksDCAxyZvtx_gt0"), dcaXyCut, mcCollision.posZ()); + // registry.fill(HIST("Purity/mc/PrimaryTracksDCAzZvtx_gt0"), dcaZCut, mcCollision.posZ()); + } } } } @@ -3322,9 +3369,10 @@ struct PseudorapidityDensityMFT { FullBCs const& bcs, MFTTracksLabeledOrg const& originalTracks, MFTTracksLabeledGenReco3d const& tracks, FiCentralTracks const& midtracks, + CentralTracksMC const& centralTracksMC, aod::McParticles const& mcParticles /*,ParticlesGen const& particlesgen*/) { - processGenReco(mcCollision, collisions, bcs, originalTracks, tracks, midtracks, mcParticles, /*particlesgen,*/ false); + processGenReco(mcCollision, collisions, bcs, originalTracks, tracks, midtracks, centralTracksMC, mcParticles, /*particlesgen,*/ false); } void processGenReco2d(McCollisionsWithExtra::iterator const& mcCollision, @@ -3332,9 +3380,10 @@ struct PseudorapidityDensityMFT { FullBCs const& bcs, MFTTracksLabeledOrg const& originalTracks, MFTTracksLabeledGenReco2d const& tracks, FiCentralTracks const& midtracks, + CentralTracksMC const& centralTracksMC, aod::McParticles const& mcParticles /*, ParticlesGen const& particlesgen*/) { - processGenReco(mcCollision, collisions, bcs, originalTracks, tracks, midtracks, mcParticles, /*particlesgen,*/ true); + processGenReco(mcCollision, collisions, bcs, originalTracks, tracks, midtracks, centralTracksMC, mcParticles, /*particlesgen,*/ true); } PROCESS_SWITCH(PseudorapidityDensityMFT, processGenReco3d, "Process gen-reco info with BestCollisionsFwd3d", true);