From 68d07d92472ed43861a1925833d2b0067ed95c1c Mon Sep 17 00:00:00 2001 From: blacwovie Date: Mon, 8 Jun 2026 18:51:21 +0800 Subject: [PATCH] add proton selection --- .../TableProducer/HadNucleiFemto.cxx | 124 +++++++++++++++++- 1 file changed, 122 insertions(+), 2 deletions(-) diff --git a/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx b/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx index e8249c71141..09a9af431e2 100644 --- a/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx +++ b/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx @@ -273,6 +273,7 @@ struct HadNucleiFemto { // Candidate topology and kinematics {"hTrackSel", "Accepted hadron tracks", {HistType::kTH1F, {{Selections::kAll, -0.5, static_cast(Selections::kAll) - 0.5}}}}, {"hTrackSelDe", "Accepted deuteron tracks", {HistType::kTH1F, {{Selections::kAll, -0.5, static_cast(Selections::kAll) - 0.5}}}}, + {"hDePairFlow", "Deuteron pair-building flow;step;counts", {HistType::kTH1F, {{3, -0.5, 2.5}}}}, {"hdcaxyNu", ";DCA_{xy} (cm)", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, {"hdcazNu", ";DCA_{z} (cm)", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, @@ -577,12 +578,45 @@ struct HadNucleiFemto { template bool selectTrackHadron(const Ttrack& candidate) { + if (settingHadPDGCode.value == static_cast(PDG_t::kProton)) { + return selectTrackProton(candidate); + } if (useReferencePionCuts()) { return selectTrackPionReference(candidate); } return selectTrack(candidate); } + template + bool selectTrackProton(const Ttrack& candidate) + { + constexpr float protonEtaMax = 0.8f; + constexpr int protonTPCNClsFoundMin = 90; + constexpr int protonTPCCrossedRowsMin = 80; + constexpr float protonDCAzMax = 0.2f; + + if (std::abs(candidate.eta()) >= protonEtaMax) { + return false; + } + + const float absPt = std::abs(candidate.pt()); + if (absPt <= 0.f) { + return false; + } + + if (candidate.tpcNClsFound() <= protonTPCNClsFoundMin || + candidate.tpcNClsCrossedRows() <= protonTPCCrossedRowsMin) { + return false; + } + + const float prDCAxyMax = 105.e-3f + 30.5e-3f / std::pow(absPt, 1.1f); + if (std::abs(candidate.dcaXY()) >= prDCAxyMax || std::abs(candidate.dcaZ()) >= protonDCAzMax) { + return false; + } + + return true; + } + template bool selectTrackDe(const Ttrack& candidate) { @@ -690,6 +724,51 @@ struct HadNucleiFemto { return isRejected; } + template + bool selectionPIDProton(const Ttrack& candidate) + { + constexpr float protonPtMin = 0.5f; + constexpr float protonPtMax = 3.0f; + constexpr float protonPCombMin = 0.75f; + constexpr float protonTPCNsigmaMax = 3.0f; + constexpr float protonCombNsigmaMax = 3.0f; + + const float tpcNSigmaPr = candidate.tpcNSigmaPr(); + mQaRegistry.fill(HIST("h2NsigmaHadTPC_preselection"), candidate.sign() * candidate.tpcInnerParam(), tpcNSigmaPr); + + if (std::abs(candidate.pt()) <= protonPtMin || std::abs(candidate.pt()) >= protonPtMax) { + return false; + } + + const float absPin = std::abs(candidate.tpcInnerParam()); + if (absPin < protonPCombMin) { + if (std::abs(tpcNSigmaPr) > protonTPCNsigmaMax) { + return false; + } + mQaRegistry.fill(HIST("h2NsigmaHadTPC"), candidate.sign() * candidate.pt(), tpcNSigmaPr); + mQaRegistry.fill(HIST("h2dEdxHadcandidates"), candidate.sign() * candidate.tpcInnerParam(), candidate.tpcSignal()); + return true; + } + + if (!candidate.hasTOF()) { + return false; + } + + const float tofNSigmaPr = candidate.tofNSigmaPr(); + const float combNsigma = std::sqrt(tpcNSigmaPr * tpcNSigmaPr + tofNSigmaPr * tofNSigmaPr); + mQaRegistry.fill(HIST("h2NsigmaHadTOF_preselection"), candidate.sign() * candidate.pt(), tofNSigmaPr); + mQaRegistry.fill(HIST("h2NsigmaHadComb_preselection"), candidate.sign() * candidate.pt(), combNsigma); + if (combNsigma > protonCombNsigmaMax) { + return false; + } + + mQaRegistry.fill(HIST("h2NsigmaHadTPC"), candidate.sign() * candidate.pt(), tpcNSigmaPr); + mQaRegistry.fill(HIST("h2NsigmaHadTOF"), candidate.sign() * candidate.pt(), tofNSigmaPr); + mQaRegistry.fill(HIST("h2NsigmaHadComb"), candidate.sign() * candidate.pt(), combNsigma); + mQaRegistry.fill(HIST("h2dEdxHadcandidates"), candidate.sign() * candidate.tpcInnerParam(), candidate.tpcSignal()); + return true; + } + template bool selectionPIDKaon(const Ttrack& candidate) { @@ -840,12 +919,30 @@ struct HadNucleiFemto { } else if (settingHadPDGCode == PDG_t::kKPlus) { PID = selectionPIDKaon(candidate); MassHad = o2::constants::physics::MassKPlus; + } else if (settingHadPDGCode == PDG_t::kProton) { + PID = selectionPIDProton(candidate); + MassHad = o2::constants::physics::MassProton; } else { LOG(info) << "invalid PDG code"; } return PID; } + template + float getHadronTPCNSigma(const Ttrack& candidate) const + { + if (settingHadPDGCode.value == static_cast(PDG_t::kPiPlus)) { + return candidate.tpcNSigmaPi(); + } + if (settingHadPDGCode.value == static_cast(PDG_t::kKPlus)) { + return candidate.tpcNSigmaKa(); + } + if (settingHadPDGCode.value == static_cast(PDG_t::kProton)) { + return candidate.tpcNSigmaPr(); + } + return -10.f; + } + template float computeNSigmaDe(const Ttrack& candidate) { @@ -1018,7 +1115,7 @@ struct HadNucleiFemto { hadNucand.nTPCClustersNu = trackDe.tpcNClsFound(); hadNucand.nSigmaNu = computeNSigmaDe(trackDe); - // hadNucand.nSigmaHad = trackHad.tpcNSigmaPi(); + hadNucand.nSigmaHad = getHadronTPCNSigma(trackHad); hadNucand.chi2TPCNu = trackDe.tpcChi2NCl(); hadNucand.chi2TPCHad = trackHad.tpcChi2NCl(); @@ -1104,7 +1201,7 @@ struct HadNucleiFemto { hadHypercand.tpcSignalHad = trackHad.tpcSignal(); hadHypercand.tpcSignalNu = V0Hyper.tpcSignalHe(); hadHypercand.momHadTPC = trackHad.tpcInnerParam(); - hadHypercand.nSigmaHad = trackHad.tpcNSigmaPi(); + hadHypercand.nSigmaHad = getHadronTPCNSigma(trackHad); hadHypercand.nSigmaNu = V0Hyper.nSigmaHe(); hadHypercand.chi2TPCHad = trackHad.tpcChi2NCl(); hadHypercand.chi2TPCNu = V0Hyper.tpcChi2He(); @@ -1146,6 +1243,10 @@ struct HadNucleiFemto { mQaRegistry.fill(HIST("hTrackSel"), Selections::kPID); mQaRegistry.fill(HIST("hSingleNuPt"), track0.pt() * track0.sign()); mQaRegistry.fill(HIST("hSingleNuPin"), track0.tpcInnerParam() * track0.sign()); + mQaRegistry.fill(HIST("hDePairFlow"), 0); + + bool hasHadronSelected = false; + bool hasStoredPair = false; for (const auto& track1 : tracks) { if (track0 == track1) { @@ -1164,6 +1265,7 @@ struct HadNucleiFemto { if (!selectTrackHadron(track1) || !selectionPIDHadron(track1)) { continue; } + hasHadronSelected = true; if (isClosePair(track0, track1)) { continue; } @@ -1175,6 +1277,14 @@ struct HadNucleiFemto { CollBracket collBracket{collIdx, collIdx}; trackPair.collBracket = collBracket; mTrackPairs.push_back(trackPair); + hasStoredPair = true; + } + + if (hasHadronSelected) { + mQaRegistry.fill(HIST("hDePairFlow"), 1); + } + if (hasStoredPair) { + mQaRegistry.fill(HIST("hDePairFlow"), 2); } } } @@ -1628,6 +1738,16 @@ PROCESS_SWITCH(HadNucleiFemto, processMixedEventHyper, "Process Mixed event", fa mQaRegistry.fill(HIST("purity/h2NsigmaHadTOF_preselection"), track.sign() * track.pt(), tofNSigmaHad); mQaRegistry.fill(HIST("purity/h2NsigmaHadComb_preselection"), track.sign() * track.pt(), combNsigmaHad); } + } else if (passTrackHad && settingHadPDGCode == PDG_t::kProton) { + constexpr float protonPCombMin = 0.75f; + const float tpcNSigmaHad = track.tpcNSigmaPr(); + mQaRegistry.fill(HIST("purity/h2NsigmaHadTPC_preselection"), track.sign() * track.pt(), tpcNSigmaHad); + if (track.hasTOF() && std::abs(track.tpcInnerParam()) >= protonPCombMin) { + const float tofNSigmaHad = track.tofNSigmaPr(); + const float combNsigmaHad = std::sqrt(tofNSigmaHad * tofNSigmaHad + tpcNSigmaHad * tpcNSigmaHad); + mQaRegistry.fill(HIST("purity/h2NsigmaHadTOF_preselection"), track.sign() * track.pt(), tofNSigmaHad); + mQaRegistry.fill(HIST("purity/h2NsigmaHadComb_preselection"), track.sign() * track.pt(), combNsigmaHad); + } } if (passTrackDe) {