From 82eb996cea841c1f5d12c7e05097b89b06fe15df Mon Sep 17 00:00:00 2001 From: Luigi Dello Stritto Date: Tue, 30 Apr 2024 17:13:01 +0200 Subject: [PATCH] PWGHF: implement track selection for HF tasks --- PWGHF/Core/SelectorCuts.h | 34 ++--- .../candidateSelectorDplusToPiKPi.cxx | 12 +- .../candidateSelectorDsToKKPi.cxx | 14 +- PWGHF/TableProducer/candidateSelectorLc.cxx | 129 ++++++++++++------ PWGHF/TableProducer/trackIndexSkimCreator.cxx | 2 +- PWGHF/Utils/utilsAnalysis.h | 48 ++++++- 6 files changed, 167 insertions(+), 72 deletions(-) diff --git a/PWGHF/Core/SelectorCuts.h b/PWGHF/Core/SelectorCuts.h index fecacb15b1e..0d662b6c08e 100644 --- a/PWGHF/Core/SelectorCuts.h +++ b/PWGHF/Core/SelectorCuts.h @@ -26,7 +26,7 @@ namespace o2::analysis namespace hf_cuts_single_track { static constexpr int nBinsPtTrack = 6; -static constexpr int nCutVarsTrack = 2; +static constexpr int nCutVarsTrack = 4; // default values for the pT bin edges (can be used to configure histogram axis) // common for any candidate type (2-prong, 3-prong) // offset by 1 from the bin numbers in cuts array @@ -40,27 +40,27 @@ constexpr double binsPtTrack[nBinsPtTrack + 1] = { 1000.0}; auto vecBinsPtTrack = std::vector{binsPtTrack, binsPtTrack + nBinsPtTrack + 1}; -// default values for the cuts of displaced tracks -constexpr double cutsTrack[nBinsPtTrack][nCutVarsTrack] = {{0.0025, 10.}, /* 0 < pt < 0.5 */ - {0.0025, 10.}, /* 0.5 < pt < 1 */ - {0.0025, 10.}, /* 1 < pt < 1.5 */ - {0.0025, 10.}, /* 1.5 < pt < 2 */ - {0.0000, 10.}, /* 2 < pt < 3 */ - {0.0000, 10.}}; /* 3 < pt < 1000 */ - -// default values for the cuts of primary tracks (e.g. D* soft pions) -constexpr double cutsTrackPrimary[nBinsPtTrack][nCutVarsTrack] = {{0.0000, 2.}, /* 0 < pt < 0.5 */ - {0.0000, 2.}, /* 0.5 < pt < 1 */ - {0.0000, 2.}, /* 1 < pt < 1.5 */ - {0.0000, 2.}, /* 1.5 < pt < 2 */ - {0.0000, 2.}, /* 2 < pt < 3 */ - {0.0000, 2.}}; /* 3 < pt < 1000 */ +// default values for the dca_xy cuts of displaced tracks +constexpr double cutsTrack[nBinsPtTrack][nCutVarsTrack] = {{0.0025, 10., 0.0000, 100.}, /* 0 < pt < 0.5 */ + {0.0025, 10., 0.0000, 100.}, /* 0.5 < pt < 1 */ + {0.0025, 10., 0.0000, 100.}, /* 1 < pt < 1.5 */ + {0.0025, 10., 0.0000, 100.}, /* 1.5 < pt < 2 */ + {0.0000, 10., 0.0000, 100.}, /* 2 < pt < 3 */ + {0.0000, 10., 0.0000, 100.}}; /* 3 < pt < 1000 */ + +// default values for the dca_xy cuts of primary tracks (e.g. D* soft pions) +constexpr double cutsTrackPrimary[nBinsPtTrack][nCutVarsTrack] = {{0.0000, 2., 0.0000, 100.}, /* 0 < pt < 0.5 */ + {0.0000, 2., 0.0000, 100.}, /* 0.5 < pt < 1 */ + {0.0000, 2., 0.0000, 100.}, /* 1 < pt < 1.5 */ + {0.0000, 2., 0.0000, 100.}, /* 1.5 < pt < 2 */ + {0.0000, 2., 0.0000, 100.}, /* 2 < pt < 3 */ + {0.0000, 2., 0.0000, 100.}}; /* 3 < pt < 1000 */ // row labels static const std::vector labelsPtTrack{}; // column labels -static const std::vector labelsCutVarTrack = {"min_dcaxytoprimary", "max_dcaxytoprimary"}; +static const std::vector labelsCutVarTrack = {"min_dcaxytoprimary", "max_dcaxytoprimary", "min_dcaztoprimary", "max_dcaztoprimary"}; } // namespace hf_cuts_single_track namespace hf_presel_pid diff --git a/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx b/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx index 7bd4a061e0a..d9b5b87fc79 100644 --- a/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx @@ -56,7 +56,7 @@ struct HfCandidateSelectorDplusToPiKPi { Configurable> cuts{"cuts", {hf_cuts_dplus_to_pi_k_pi::cuts[0], hf_cuts_dplus_to_pi_k_pi::nBinsPt, hf_cuts_dplus_to_pi_k_pi::nCutVars, hf_cuts_dplus_to_pi_k_pi::labelsPt, hf_cuts_dplus_to_pi_k_pi::labelsCutVar}, "Dplus candidate selection per pT bin"}; // DCAxy selections Configurable> cutsSingleTrack{"cutsSingleTrack", {hf_cuts_single_track::cutsTrack[0], hf_cuts_single_track::nBinsPtTrack, hf_cuts_single_track::nCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, "Single-track selections"}; - Configurable> binsPtTrack{"binsPtTrack", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "track pT bin limits for DCA XY pT-dependent cut"}; + Configurable> binsPtTrack{"binsPtTrack", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "track pT bin limits for DCA pT-dependent cut"}; // QA switch Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; // ML inference @@ -164,7 +164,7 @@ struct HfCandidateSelectorDplusToPiKPi { if (std::abs(candidate.maxNormalisedDeltaIP()) > cuts->get(pTBin, "max normalized deltaIP")) { return false; } - if (!isSelectedCandidateDcaXY(candidate)) { + if (!isSelectedCandidateDca(candidate)) { return false; } return true; @@ -174,11 +174,11 @@ struct HfCandidateSelectorDplusToPiKPi { /// \param candidate is the Ds candidate /// \return true if all the prongs pass the selections template - bool isSelectedCandidateDcaXY(const T1& candidate) + bool isSelectedCandidateDca(const T1& candidate) { - return (isSelectedTrackDcaXY(binsPtTrack, cutsSingleTrack, candidate.ptProng0(), candidate.impactParameter0()) && - isSelectedTrackDcaXY(binsPtTrack, cutsSingleTrack, candidate.ptProng1(), candidate.impactParameter1()) && - isSelectedTrackDcaXY(binsPtTrack, cutsSingleTrack, candidate.ptProng2(), candidate.impactParameter2())); + return (isSelectedTrackDca(binsPtTrack, cutsSingleTrack, candidate.ptProng0(), candidate.impactParameter0(), candidate.impactParameterZ0()) && + isSelectedTrackDca(binsPtTrack, cutsSingleTrack, candidate.ptProng1(), candidate.impactParameter1(), candidate.impactParameterZ1()) && + isSelectedTrackDca(binsPtTrack, cutsSingleTrack, candidate.ptProng2(), candidate.impactParameter2(), candidate.impactParameterZ2())); } /// Apply PID selection diff --git a/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx b/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx index 9127f0a7fa7..f92eee69ddd 100644 --- a/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx @@ -52,10 +52,10 @@ struct HfCandidateSelectorDsToKKPi { // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_ds_to_k_k_pi::vecBinsPt}, "pT bin limits"}; Configurable> cuts{"cuts", {hf_cuts_ds_to_k_k_pi::cuts[0], hf_cuts_ds_to_k_k_pi::nBinsPt, hf_cuts_ds_to_k_k_pi::nCutVars, hf_cuts_ds_to_k_k_pi::labelsPt, hf_cuts_ds_to_k_k_pi::labelsCutVar}, "Ds candidate selection per pT bin"}; - // DCAxy selections + // DCAxy and DCAz selections Configurable> cutsSingleTrack{"cutsSingleTrack", {hf_cuts_single_track::cutsTrack[0], hf_cuts_single_track::nBinsPtTrack, hf_cuts_single_track::nCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, "Single-track selections"}; // pT bins for single-track cuts - Configurable> binsPtTrack{"binsPtTrack", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "track pT bin limits for DCA XY pT-dependent cut"}; + Configurable> binsPtTrack{"binsPtTrack", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "track pT bin limits for DCA pT-dependent cut"}; // QA switch Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; // ML inference @@ -126,11 +126,11 @@ struct HfCandidateSelectorDsToKKPi { /// \param candidate is the Ds candidate /// \return true if all the prongs pass the selections template - bool isSelectedCandidateDcaXY(const T1& candidate) + bool isSelectedCandidateDca(const T1& candidate) { - if (isSelectedTrackDcaXY(binsPtTrack, cutsSingleTrack, candidate.ptProng0(), candidate.impactParameter0()) && - isSelectedTrackDcaXY(binsPtTrack, cutsSingleTrack, candidate.ptProng1(), candidate.impactParameter1()) && - isSelectedTrackDcaXY(binsPtTrack, cutsSingleTrack, candidate.ptProng2(), candidate.impactParameter2())) { + if (isSelectedTrackDca(binsPtTrack, cutsSingleTrack, candidate.ptProng0(), candidate.impactParameter0(), candidate.impactParameterZ0()) && + isSelectedTrackDca(binsPtTrack, cutsSingleTrack, candidate.ptProng1(), candidate.impactParameter1(), candidate.impactParameterZ1()) && + isSelectedTrackDca(binsPtTrack, cutsSingleTrack, candidate.ptProng2(), candidate.impactParameter2(), candidate.impactParameterZ2())) { return true; } return false; @@ -169,7 +169,7 @@ struct HfCandidateSelectorDsToKKPi { if (candidate.chi2PCA() > cuts->get(pTBin, "chi2PCA")) { return false; } - if (!isSelectedCandidateDcaXY(candidate)) { + if (!isSelectedCandidateDca(candidate)) { return false; } return true; diff --git a/PWGHF/TableProducer/candidateSelectorLc.cxx b/PWGHF/TableProducer/candidateSelectorLc.cxx index 25b13bc8821..6c9c801b093 100644 --- a/PWGHF/TableProducer/candidateSelectorLc.cxx +++ b/PWGHF/TableProducer/candidateSelectorLc.cxx @@ -57,6 +57,16 @@ struct HfCandidateSelectorLc { Configurable ptPidBayesMax{"ptPidBayesMax", 100, "Upper bound of track pT for Bayesian PID"}; // Combined PID options Configurable usePidTpcAndTof{"usePidTpcAndTof", false, "Bool to decide how to combine TPC and TOF PID: true = both (if present, only one otherwise); false = one is enough"}; + // Single track cuts + Configurable tpcNClsFoundMin{"tpcNClsFoundMin", 0, "min number of found TPC clusters"}; + Configurable tpcNCrossedRowsMin{"tpcNCrossedRowsMin", 0, "min number of crossed rows in TPC"}; + Configurable tpcNCrossedRowsOverFindableClustersMin{"tpcNCrossedRowsOverFindableClustersMin", 0., "min ratio crossed rows / findable clusters"}; + Configurable tpcChi2PerClusterMax{"tpcChi2PerClusterMax", 1e10f, "max tpc fit chi2 per TPC cluster"}; + Configurable itsNClsFoundMin{"itsNClsFoundMin", 0, "min. number of found ITS clusters"}; + Configurable itsChi2PerClusterMax{"itsChi2PerClusterMax", 1e10f, "max its fit chi2 per ITS cluster"}; + // DCA track cuts + Configurable> binsPtTrack{"binsPtTrack", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "track pT bin limits for DCA XY/Z pT-dependent cut"}; + Configurable> cutsSingleTrack{"cutsSingleTrack", {hf_cuts_single_track::cutsTrack[0], hf_cuts_single_track::nBinsPtTrack, hf_cuts_single_track::nCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, "Single-track selections"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_lc_to_p_k_pi::vecBinsPt}, "pT bin limits"}; Configurable> cuts{"cuts", {hf_cuts_lc_to_p_k_pi::cuts[0], hf_cuts_lc_to_p_k_pi::nBinsPt, hf_cuts_lc_to_p_k_pi::nCutVars, hf_cuts_lc_to_p_k_pi::labelsPt, hf_cuts_lc_to_p_k_pi::labelsCutVar}, "Lc candidate selection per pT bin"}; @@ -131,6 +141,25 @@ struct HfCandidateSelectorLc { } } + /// Single track quality cuts + /// \param track is track + /// \return true if track passes all cuts + template + bool selectionTrackQuality(const T& trackPos1, const T& trackNeg, const T& trackPos2, int tpcNClsFoundMin, int tpcNCrossedRowsMin, float tpcNCrossedRowsOverFindableClustersMin, float tpcChi2PerClusterMax, int itsNClsFoundMin, float itsChi2PerClusterMax) + { + if (!isTpcQualityCuts(trackPos1, tpcNClsFoundMin, tpcNCrossedRowsMin, tpcNCrossedRowsOverFindableClustersMin, tpcChi2PerClusterMax) && + !isTpcQualityCuts(trackNeg, tpcNClsFoundMin, tpcNCrossedRowsMin, tpcNCrossedRowsOverFindableClustersMin, tpcChi2PerClusterMax) && + !isTpcQualityCuts(trackPos2, tpcNClsFoundMin, tpcNCrossedRowsMin, tpcNCrossedRowsOverFindableClustersMin, tpcChi2PerClusterMax)) { + return false; + } + if (!isItsQualityCuts(trackPos1, itsNClsFoundMin, itsChi2PerClusterMax) && + !isItsQualityCuts(trackNeg, itsNClsFoundMin, itsChi2PerClusterMax) && + !isItsQualityCuts(trackPos2, itsNClsFoundMin, itsChi2PerClusterMax)) { + return false; + } + return true; + } + /// Conjugate-independent topological cuts /// \param candidate is candidate /// \return true if candidate passes all cuts @@ -162,6 +191,11 @@ struct HfCandidateSelectorLc { if (candidate.decayLength() <= cuts->get(pTBin, "decay length")) { return false; } + + if (!isSelectedCandidateDca(candidate)) { + return false; + } + return true; } @@ -199,6 +233,33 @@ struct HfCandidateSelectorLc { return true; } + /// Single-track dca_xy and dca_z cuts + /// \param candidate is the Lc candidate + /// \return true if all the prongs pass the selections + template + bool isSelectedCandidateDca(const T1& candidate) + { + return (isSelectedTrackDca(binsPtTrack, cutsSingleTrack, candidate.ptProng0(), candidate.impactParameter0(), candidate.impactParameterZ0()) && + isSelectedTrackDca(binsPtTrack, cutsSingleTrack, candidate.ptProng1(), candidate.impactParameter1(), candidate.impactParameterZ1()) && + isSelectedTrackDca(binsPtTrack, cutsSingleTrack, candidate.ptProng2(), candidate.impactParameter2(), candidate.impactParameterZ2())); + } + + /// Apply PID selection + /// \param pidTrackPos1 is the PID status of trackPos1 (prong0 of Lc candidate) + /// \param pidTrackNeg is the PID status of trackNeg (prong1 of Lc candidate) + /// \param pidTrackPos2 is the PID status of trackPos2 (prong2 of Lc candidate) + /// \return true if prongs pass all selections + template + bool isSelectedPID(const T& pidTrackPos1, const T& pidTrackNeg, const T& pidTrackPos2) + { + if (pidTrackPos1 == TrackSelectorPID::Rejected || + pidTrackNeg == TrackSelectorPID::Rejected || + pidTrackPos2 == TrackSelectorPID::Rejected) { + return false; + } + return true; + } + void process(aod::HfCand3Prong const& candidates, TracksSel const&) { @@ -235,6 +296,16 @@ struct HfCandidateSelectorLc { // implement filter bit 4 cut - should be done before this task at the track selection level + // track quality selection + bool trackQualitySel = selectionTrackQuality(trackPos1, trackNeg, trackPos2, tpcNClsFoundMin, tpcNCrossedRowsMin, tpcNCrossedRowsOverFindableClustersMin, tpcChi2PerClusterMax, itsNClsFoundMin, itsChi2PerClusterMax); + if (!trackQualitySel) { + hfSelLcCandidate(statusLcToPKPi, statusLcToPiKP); + if (applyMl) { + hfMlLcToPKPiCandidate(outputMlLcToPKPi, outputMlLcToPiKP); + } + continue; + } + // conjugate-independent topological selection if (!selectionTopol(candidate)) { hfSelLcCandidate(statusLcToPKPi, statusLcToPiKP); @@ -245,7 +316,6 @@ struct HfCandidateSelectorLc { } // conjugate-dependent topological selection for Lc - bool topolLcToPKPi = selectionTopolConjugate(candidate, trackPos1, trackNeg, trackPos2); bool topolLcToPiKP = selectionTopolConjugate(candidate, trackPos2, trackNeg, trackPos1); @@ -291,23 +361,15 @@ struct HfCandidateSelectorLc { pidTrackNegKaon = selectorKaon.statusTpcOrTof(trackNeg); } - if (pidTrackPos1Proton == TrackSelectorPID::Accepted && - pidTrackNegKaon == TrackSelectorPID::Accepted && - pidTrackPos2Pion == TrackSelectorPID::Accepted) { + if (isSelectedPID(pidTrackPos1Proton, pidTrackNegKaon, pidTrackPos2Pion)) { pidLcToPKPi = 1; // accept LcToPKPi - } else if (pidTrackPos1Proton == TrackSelectorPID::Rejected || - pidTrackNegKaon == TrackSelectorPID::Rejected || - pidTrackPos2Pion == TrackSelectorPID::Rejected) { - pidLcToPKPi = 0; // exclude LcToPKPi + } else { + pidLcToPKPi = 0; // reject LcToPKPi } - if (pidTrackPos2Proton == TrackSelectorPID::Accepted && - pidTrackNegKaon == TrackSelectorPID::Accepted && - pidTrackPos1Pion == TrackSelectorPID::Accepted) { + if (isSelectedPID(pidTrackPos2Proton, pidTrackNegKaon, pidTrackPos1Pion)) { pidLcToPiKP = 1; // accept LcToPiKP - } else if (pidTrackPos1Pion == TrackSelectorPID::Rejected || - pidTrackNegKaon == TrackSelectorPID::Rejected || - pidTrackPos2Proton == TrackSelectorPID::Rejected) { - pidLcToPiKP = 0; // exclude LcToPiKP + } else { + pidLcToPiKP = 0; // accept LcToPiKP } } @@ -322,42 +384,31 @@ struct HfCandidateSelectorLc { int pidBayesTrackPos2Pion = selectorPion.statusBayes(trackPos2); int pidBayesTrackNegKaon = selectorKaon.statusBayes(trackNeg); - if (pidBayesTrackPos1Proton == TrackSelectorPID::Accepted && - pidBayesTrackNegKaon == TrackSelectorPID::Accepted && - pidBayesTrackPos2Pion == TrackSelectorPID::Accepted) { + if (isSelectedPID(pidBayesTrackPos1Proton, pidBayesTrackNegKaon, pidBayesTrackPos2Pion)) { pidBayesLcToPKPi = 1; // accept LcToPKPi - } else if (pidBayesTrackPos1Proton == TrackSelectorPID::Rejected || - pidBayesTrackNegKaon == TrackSelectorPID::Rejected || - pidBayesTrackPos2Pion == TrackSelectorPID::Rejected) { - pidBayesLcToPKPi = 0; // exclude LcToPKPi + } else { + pidBayesLcToPKPi = 0; // reject LcToPKPi } - if (pidBayesTrackPos2Proton == TrackSelectorPID::Accepted && - pidBayesTrackNegKaon == TrackSelectorPID::Accepted && - pidBayesTrackPos1Pion == TrackSelectorPID::Accepted) { + + if (isSelectedPID(pidBayesTrackPos2Proton, pidBayesTrackNegKaon, pidBayesTrackPos1Pion)) { pidBayesLcToPiKP = 1; // accept LcToPiKP - } else if (pidBayesTrackPos1Pion == TrackSelectorPID::Rejected || - pidBayesTrackNegKaon == TrackSelectorPID::Rejected || - pidBayesTrackPos2Proton == TrackSelectorPID::Rejected) { - pidBayesLcToPiKP = 0; // exclude LcToPiKP + } else { + pidBayesLcToPiKP = 0; // reject LcToPiKP } } - if (pidLcToPKPi == 0 && pidLcToPiKP == 0) { + if ((pidLcToPKPi == 0 && pidLcToPiKP == 0) || (pidBayesLcToPKPi == 0 && pidBayesLcToPiKP == 0)) { hfSelLcCandidate(statusLcToPKPi, statusLcToPiKP); if (applyMl) { hfMlLcToPKPiCandidate(outputMlLcToPKPi, outputMlLcToPiKP); } continue; } + if (activateQA) { registry.fill(HIST("hSelections"), 2 + aod::SelectionStep::RecoPID, candidate.pt()); } - if (pidBayesLcToPKPi == 0 && pidBayesLcToPiKP == 0) { - hfSelLcCandidate(statusLcToPKPi, statusLcToPiKP); - continue; - } - bool isSelectedMlLcToPKPi = true; bool isSelectedMlLcToPiKP = true; if (applyMl) { @@ -365,11 +416,11 @@ struct HfCandidateSelectorLc { isSelectedMlLcToPKPi = false; isSelectedMlLcToPiKP = false; - if ((pidLcToPKPi == -1 || pidLcToPKPi == 1) && (pidBayesLcToPKPi == -1 || pidBayesLcToPKPi == 1) && topolLcToPKPi) { + if (pidLcToPKPi == 1 && pidBayesLcToPKPi == 1 && topolLcToPKPi) { std::vector inputFeaturesLcToPKPi = hfMlResponse.getInputFeatures(candidate, trackPos1, trackNeg, trackPos2); isSelectedMlLcToPKPi = hfMlResponse.isSelectedMl(inputFeaturesLcToPKPi, candidate.pt(), outputMlLcToPKPi); } - if ((pidLcToPiKP == -1 || pidLcToPiKP == 1) && (pidBayesLcToPiKP == -1 || pidBayesLcToPiKP == 1) && topolLcToPiKP) { + if (pidLcToPiKP == 1 && pidBayesLcToPiKP == 1 && topolLcToPiKP) { std::vector inputFeaturesLcToPiKP = hfMlResponse.getInputFeatures(candidate, trackPos1, trackNeg, trackPos2); isSelectedMlLcToPiKP = hfMlResponse.isSelectedMl(inputFeaturesLcToPiKP, candidate.pt(), outputMlLcToPiKP); } @@ -386,10 +437,10 @@ struct HfCandidateSelectorLc { } } - if ((pidLcToPKPi == -1 || pidLcToPKPi == 1) && (pidBayesLcToPKPi == -1 || pidBayesLcToPKPi == 1) && isSelectedMlLcToPKPi && topolLcToPKPi) { + if ( pidLcToPKPi == 1 && pidBayesLcToPKPi == 1 && isSelectedMlLcToPKPi && topolLcToPKPi && trackQualitySel) { statusLcToPKPi = 1; // identified as LcToPKPi } - if ((pidLcToPiKP == -1 || pidLcToPiKP == 1) && (pidBayesLcToPiKP == -1 || pidBayesLcToPiKP == 1) && isSelectedMlLcToPiKP && topolLcToPiKP) { + if (pidLcToPiKP == 1 && pidBayesLcToPiKP == 1 && isSelectedMlLcToPiKP && topolLcToPiKP && trackQualitySel) { statusLcToPiKP = 1; // identified as LcToPiKP } diff --git a/PWGHF/TableProducer/trackIndexSkimCreator.cxx b/PWGHF/TableProducer/trackIndexSkimCreator.cxx index 0b55ab23b6f..edced2a809b 100644 --- a/PWGHF/TableProducer/trackIndexSkimCreator.cxx +++ b/PWGHF/TableProducer/trackIndexSkimCreator.cxx @@ -636,7 +636,7 @@ struct HfTrackIndexSkimCreatorTagSelTracks { iCut = 5; if (statusProng > 0) { for (int iCandType = 0; iCandType < CandidateType::NCandidateTypes; ++iCandType) { - if (TESTBIT(statusProng, iCandType) && !isSelectedTrackDcaXY(binsPtTrack, &cutsSingleTrack[iCandType], trackPt, dca[0])) { + if (TESTBIT(statusProng, iCandType) && !isSelectedTrackDca(binsPtTrack, &cutsSingleTrack[iCandType], trackPt, dca[0], dca[1])) { CLRBIT(statusProng, iCandType); if (fillHistograms) { registry.fill(HIST("hRejTracks"), (nCuts + 1) * iCandType + iCut); diff --git a/PWGHF/Utils/utilsAnalysis.h b/PWGHF/Utils/utilsAnalysis.h index 3296113e806..d8383c2d82e 100644 --- a/PWGHF/Utils/utilsAnalysis.h +++ b/PWGHF/Utils/utilsAnalysis.h @@ -37,14 +37,15 @@ int findBin(T1 const& binsPt, T2 value) return std::distance(binsPt->begin(), std::upper_bound(binsPt->begin(), binsPt->end(), value)) - 1; } -/// Single-track cut on DCAxy +/// Single-track cut on DCAxy and DCAz /// \param binsPt pT bins /// \param cuts cut configuration /// \param pt is the prong pT /// \param dcaXY is the prong dcaXY +/// \param dcaZ is the prong dcaZ /// \return true if track passes all cuts template -bool isSelectedTrackDcaXY(T1 const& binsPt, T2 const& cuts, const float pt, const float dcaXY) +bool isSelectedTrackDca(T1 const& binsPt, T2 const& cuts, const float pt, const float dcaXY, const float dcaZ) { auto binPt = findBin(binsPt, pt); if (binPt == -1) { @@ -56,9 +57,52 @@ bool isSelectedTrackDcaXY(T1 const& binsPt, T2 const& cuts, const float pt, cons if (std::abs(dcaXY) > cuts->get(binPt, "max_dcaxytoprimary")) { return false; // maximum DCAxy } + if (std::abs(dcaZ) < cuts->get(binPt, "min_dcaztoprimary")) { + return false; // minimum DCAz + } + if (std::abs(dcaZ) > cuts->get(binPt, "max_dcaztoprimary")) { + return false; // maximum DCAz + } + return true; +} + +/// Single-track cut on ITS track properties +/// \param track track that has to satisfy the selection criteria +/// \return true if track passes all cuts +template +bool isItsQualityCuts(Track const& track, int itsNClsFoundMin, float itsChi2PerClusterMax) +{ + if (track.itsNCls() < itsNClsFoundMin) { + return false; + } + if (track.itsChi2NCl() > itsChi2PerClusterMax) { + return false; + } return true; } +/// Single-track cut on TPC track properties +/// \param track track that has to satisfy the selection criteria +/// \return true if track passes all cuts +template +bool isTpcQualityCuts(Track const& track, int tpcNClsFoundMin, int tpcNCrossedRowsMin, float tpcNCrossedRowsOverFindableClustersMin, float tpcChi2PerClusterMax) +{ + if (track.tpcNClsFound() < tpcNClsFoundMin) { + return false; + } + if (track.tpcNClsCrossedRows() < tpcNCrossedRowsMin) { + return false; + } + if (track.tpcCrossedRowsOverFindableCls() < tpcNCrossedRowsOverFindableClustersMin) { + return false; + } + if (track.tpcChi2NCl() > tpcChi2PerClusterMax ) { + return false; + } + return true; +} + + } // namespace o2::analysis #endif // PWGHF_UTILS_UTILSANALYSIS_H_