@@ -72,7 +72,10 @@ struct HfCandidateSelectorLc {
7272 Configurable<LabeledArray<double >> 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" };
7373 // topological cuts
7474 Configurable<std::vector<double >> binsPt{" binsPt" , std::vector<double >{hf_cuts_lc_to_p_k_pi::vecBinsPt}, " pT bin limits" };
75- Configurable<LabeledArray<double >> 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" };
75+ Configurable<LabeledArray<double >> 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" };
76+ Configurable<LabeledArray<double >> kfCuts{" kfCuts" , {hf_cuts_lc_to_p_k_pi::kfCuts[0 ], hf_cuts_lc_to_p_k_pi::NBinsPt, hf_cuts_lc_to_p_k_pi::nKfCutVars, hf_cuts_lc_to_p_k_pi::labelsPt, hf_cuts_lc_to_p_k_pi::labelsKfCutVar}, " Lc candidate selection per pT bin with KF-associated variables" };
77+ Configurable<bool > applyNonKfCuts{" applyNonKfCuts" , true , " Whether to apply non-KF cuts when running in KF mode. In DCAFitter mode this field is not effective" };
78+ Configurable<bool > applyKfCuts{" applyKfCuts" , true , " Whether to apply KF cuts when running in KF mode. In DCAFitter mode this field is not effective" };
7679 // QA switch
7780 Configurable<bool > activateQA{" activateQA" , false , " Flag to enable QA histogram" };
7881 // ML inference
@@ -175,7 +178,7 @@ struct HfCandidateSelectorLc {
175178 // / Conjugate-independent topological cuts
176179 // / \param candidate is candidate
177180 // / \return true if candidate passes all cuts
178- template <typename T>
181+ template <aod::hf_cand::VertexerType reconstructionType, typename T>
179182 bool selectionTopol (const T& candidate)
180183 {
181184 auto candpT = candidate.pt ();
@@ -190,33 +193,52 @@ struct HfCandidateSelectorLc {
190193 return false ;
191194 }
192195
193- // cosine of pointing angle
194- if (candidate.cpa () <= cuts->get (pTBin, " cos pointing angle" )) {
195- return false ;
196- }
196+ if (reconstructionType == aod::hf_cand::VertexerType::DCAFitter || (reconstructionType == aod::hf_cand::VertexerType::KfParticle && applyNonKfCuts)) {
197+ // cosine of pointing angle
198+ if (candidate.cpa () <= cuts->get (pTBin, " cos pointing angle" )) {
199+ return false ;
200+ }
197201
198- // candidate chi2PCA
199- if (candidate.chi2PCA () > cuts->get (pTBin, " Chi2PCA" )) {
200- return false ;
201- }
202+ // candidate chi2PCA
203+ if (candidate.chi2PCA () > cuts->get (pTBin, " Chi2PCA" )) {
204+ return false ;
205+ }
202206
203- if (candidate.decayLength () <= cuts->get (pTBin, " decay length" )) {
204- return false ;
205- }
207+ if (candidate.decayLength () <= cuts->get (pTBin, " decay length" )) {
208+ return false ;
209+ }
206210
207- // candidate decay length XY
208- if (candidate.decayLengthXY () <= cuts->get (pTBin, " decLengthXY" )) {
209- return false ;
210- }
211+ // candidate decay length XY
212+ if (candidate.decayLengthXY () <= cuts->get (pTBin, " decLengthXY" )) {
213+ return false ;
214+ }
211215
212- // candidate normalized decay length XY
213- if (candidate.decayLengthXYNormalised () < cuts->get (pTBin, " normDecLXY" )) {
214- return false ;
216+ // candidate normalized decay length XY
217+ if (candidate.decayLengthXYNormalised () < cuts->get (pTBin, " normDecLXY" )) {
218+ return false ;
219+ }
220+
221+ // candidate impact parameter XY
222+ if (std::abs (candidate.impactParameterXY ()) > cuts->get (pTBin, " impParXY" )) {
223+ return false ;
224+ }
215225 }
216226
217- // candidate impact parameter XY
218- if (std::abs (candidate.impactParameterXY ()) > cuts->get (pTBin, " impParXY" )) {
219- return false ;
227+ if (reconstructionType == aod::hf_cand::VertexerType::KfParticle && applyKfCuts) {
228+ // candidate chi2geo of the triplet of prongs
229+ if (candidate.kfChi2Geo () > kfCuts->get (pTBin, " kfChi2Geo" )) {
230+ return false ;
231+ }
232+
233+ // candidate's decay point separation from the PV in terms of its error
234+ if (candidate.kfDecayLength () / candidate.kfDecayLengthError () < kfCuts->get (pTBin, " kfLdL" )) {
235+ return false ;
236+ }
237+
238+ // candidate's chi2 to the PV
239+ if (candidate.kfChi2Topo () > kfCuts->get (pTBin, " kfChi2Topo" )) {
240+ return false ;
241+ }
220242 }
221243
222244 if (!isSelectedCandidateProngDca (candidate)) {
@@ -242,13 +264,6 @@ struct HfCandidateSelectorLc {
242264 return false ;
243265 }
244266
245- // cut on daughter pT
246- if (trackProton.pt () < cuts->get (pTBin, " pT p" ) || trackKaon.pt () < cuts->get (pTBin, " pT K" ) || trackPion.pt () < cuts->get (pTBin, " pT Pi" )) {
247- return false ;
248- }
249-
250- // cut on Lc->pKpi, piKp mass values
251- // / cut on the Kpi pair invariant mass, to study Lc->pK*(->Kpi)
252267 float massLc, massKPi;
253268 if constexpr (reconstructionType == aod::hf_cand::VertexerType::DCAFitter) {
254269 if (trackProton.globalIndex () == candidate.prong0Id ()) {
@@ -268,14 +283,96 @@ struct HfCandidateSelectorLc {
268283 }
269284 }
270285
271- if (std::abs (massLc - o2::constants::physics::MassLambdaCPlus) > cuts->get (pTBin, " m" )) {
272- return false ;
286+ if (reconstructionType == aod::hf_cand::VertexerType::DCAFitter || (reconstructionType == aod::hf_cand::VertexerType::KfParticle && applyNonKfCuts)) {
287+ // cut on daughter pT
288+ if (trackProton.pt () < cuts->get (pTBin, " pT p" ) || trackKaon.pt () < cuts->get (pTBin, " pT K" ) || trackPion.pt () < cuts->get (pTBin, " pT Pi" )) {
289+ return false ;
290+ }
291+
292+ // cut on Lc->pKpi, piKp mass values
293+ if (std::abs (massLc - o2::constants::physics::MassLambdaCPlus) > cuts->get (pTBin, " m" )) {
294+ return false ;
295+ }
296+
297+ // / cut on the Kpi pair invariant mass, to study Lc->pK*(->Kpi)
298+ const double cutMassKPi = cuts->get (pTBin, " mass (Kpi)" );
299+ if (cutMassKPi > 0 && std::abs (massKPi - massK0Star892) > cutMassKPi) {
300+ return false ;
301+ }
273302 }
274303
275- // / cut on the Kpi pair invariant mass, to study Lc->pK*(->Kpi)
276- const double cutMassKPi = cuts->get (pTBin, " mass (Kpi)" );
277- if (cutMassKPi > 0 && std::abs (massKPi - massK0Star892) > cutMassKPi) {
278- return false ;
304+ if (reconstructionType == aod::hf_cand::VertexerType::KfParticle && applyKfCuts) {
305+
306+ const float chi2PrimProng0 = candidate.kfChi2PrimProng0 ();
307+ const float chi2PrimProng1 = candidate.kfChi2PrimProng1 ();
308+ const float chi2PrimProng2 = candidate.kfChi2PrimProng2 ();
309+
310+ const float chi2GeoProng1Prong2 = candidate.kfGeoProng1Prong2 ();
311+ const float chi2GeoProng0Prong2 = candidate.kfGeoProng0Prong2 ();
312+ const float chi2GeoProng0Prong1 = candidate.kfGeoProng0Prong1 ();
313+
314+ const float dcaProng1Prong2 = candidate.kfDcaProng1Prong2 ();
315+ const float dcaProng0Prong2 = candidate.kfDcaProng0Prong2 ();
316+ const float dcaProng0Prong1 = candidate.kfDcaProng0Prong1 ();
317+
318+ const double cutChi2PrimPr = kfCuts->get (pTBin, " kfChi2PrimPr" );
319+ const double cutChi2PrimKa = kfCuts->get (pTBin, " kfChi2PrimKa" );
320+ const double cutChi2PrimPi = kfCuts->get (pTBin, " kfChi2PrimPi" );
321+
322+ const double cutChi2GeoKaPi = kfCuts->get (pTBin, " kfChi2GeoKaPi" );
323+ const double cutChi2GeoPrPi = kfCuts->get (pTBin, " kfChi2GeoPrPi" );
324+ const double cutChi2GeoPrKa = kfCuts->get (pTBin, " kfChi2GeoPrKa" );
325+
326+ const double cutDcaKaPi = kfCuts->get (pTBin, " kfDcaKaPi" );
327+ const double cutDcaPrPi = kfCuts->get (pTBin, " kfDcaPrPi" );
328+ const double cutDcaPrKa = kfCuts->get (pTBin, " kfDcaPrKa" );
329+
330+ // kaon's chi2 to the PV
331+ if (chi2PrimProng1 < cutChi2PrimKa) {
332+ return false ;
333+ }
334+
335+ // chi2geo between proton and pion
336+ if (chi2GeoProng0Prong2 > cutChi2GeoPrPi) {
337+ return false ;
338+ }
339+
340+ // dca between proton and pion
341+ if (dcaProng0Prong2 > cutDcaPrPi) {
342+ return false ;
343+ }
344+
345+ const bool isPKPi = trackProton.globalIndex () == candidate.prong0Id ();
346+
347+ // 0-th prong chi2 to the PV
348+ if (chi2PrimProng0 < (isPKPi ? cutChi2PrimPr : cutChi2PrimPi)) {
349+ return false ;
350+ }
351+
352+ // 2-nd prong chi2 to the PV
353+ if (chi2PrimProng2 < (isPKPi ? cutChi2PrimPi : cutChi2PrimPr)) {
354+ return false ;
355+ }
356+
357+ // chi2geo between 1-st and 2-nd prongs
358+ if (chi2GeoProng1Prong2 > (isPKPi ? cutChi2GeoKaPi : cutChi2GeoPrKa)) {
359+ return false ;
360+ }
361+
362+ // chi2geo between 0-th and 1-st prongs
363+ if (chi2GeoProng0Prong1 > (isPKPi ? cutChi2GeoPrKa : cutChi2GeoKaPi)) {
364+ return false ;
365+ }
366+
367+ // dca between 1-st and 2-nd prongs
368+ if (dcaProng1Prong2 > (isPKPi ? cutDcaKaPi : cutDcaPrKa)) {
369+ return false ;
370+ }
371+
372+ // dca between 0-th and 1-st prongs
373+ if (dcaProng0Prong1 > (isPKPi ? cutDcaPrKa : cutDcaKaPi)) {
374+ return false ;
375+ }
279376 }
280377
281378 return true ;
0 commit comments