@@ -95,16 +95,12 @@ struct phiflow {
9595 Configurable<bool > usePID{" usePID" , true , " Flag for using PID selection for kaon meson track" };
9696 Configurable<float > nsigmaCutTPCKaMeson{" nsigmaCutTPCKaMeson" , 3.0 , " Maximum nsigma cut TPC for kaon meson track" };
9797 Configurable<float > nsigmaCutTOFKaMeson{" nsigmaCutTOFKaMeson" , 3.0 , " Maximum nsigma cut TOF for kaon meson track" };
98- Configurable<float > cutTOFBetaKaMeson{" cutTOFBetaKaMeson" , 1.0 , " Maximum beta cut for kaon meson track" };
98+ Configurable<float > cutTOFBetaKaMeson{" cutTOFBetaKaMeson" , 0 .5f , " Maximum beta cut for kaon meson track" };
99+ Configurable<float > pSwitchPID{" pSwitchPID" , 0 .5f , " pT switch for pT-dependent kaon PID" };
100+ Configurable<float > pSwitchAsymPID{" pSwitchAsymPID" , 0 .7f , " Momentum switch for asymmetric kaon PID" };
101+ Configurable<bool > applyTOFAsymPID{" applyTOFAsymPID" , true , " Apply TOF requirement in PID7" };
99102 } grpKaon;
100103
101- enum KaonPidBits : uint8_t {
102- kPID1 = 1u << 0 , // selectionPID
103- kPID2 = 1u << 1 , // selectionPID2
104- kPID3 = 1u << 2 , // selectionPID3
105- kPID4 = 1u << 3 // selectionPID4
106- };
107-
108104 HistogramRegistry histos{" histos" , {}, OutputObjHandlingPolicy::AnalysisObject};
109105 RCTFlagsChecker rctChecker;
110106 void init (o2::framework::InitContext&)
@@ -129,46 +125,75 @@ struct phiflow {
129125 candidate.pt () >= grpKaon.cutPTKaMeson ;
130126 }
131127
128+ enum KaonPidBits : uint8_t {
129+ kPID1 = 1u << 0 , // TOF-availability-dependent rectangular PID
130+ kPID2 = 1u << 1 , // TOF-availability-dependent circular PID
131+ kPID3 = 1u << 2 , // pT-dependent circular PID
132+ kPID4 = 1u << 3 , // pT-dependent rectangular PID, phi-v2-like
133+ kPID5 = 1u << 4 , // TOF-only PID
134+ kPID6 = 1u << 5 , // Momentum-dependent asymmetric TOF PID
135+ kPID7 = 1u << 6 // Optional-TOF asymmetric PID
136+ };
137+
132138 template <typename T>
133139 bool selectionPID (const T& candidate)
134140 {
135- if (!candidate.hasTOF () && std::abs (candidate.tpcNSigmaKa ()) < grpKaon.nsigmaCutTPCKaMeson ) {
136- return true ;
141+ const float nTPC = candidate.tpcNSigmaKa ();
142+
143+ // No TOF hit: TPC-only PID at all pT.
144+ if (!candidate.hasTOF ()) {
145+ return std::abs (nTPC) < grpKaon.nsigmaCutTPCKaMeson ;
137146 }
138- if (candidate.hasTOF () && candidate.beta () > grpKaon.cutTOFBetaKaMeson && std::abs (candidate.tpcNSigmaKa ()) < grpKaon.nsigmaCutTPCKaMeson && std::abs (candidate.tofNSigmaKa ()) < grpKaon.nsigmaCutTOFKaMeson ) {
139- return true ;
147+
148+ // TOF hit: require beta, TPC PID, and TOF PID.
149+ if (candidate.beta () <= grpKaon.cutTOFBetaKaMeson ) {
150+ return false ;
140151 }
141- return false ;
152+
153+ return std::abs (nTPC) < grpKaon.nsigmaCutTPCKaMeson &&
154+ std::abs (candidate.tofNSigmaKa ()) < grpKaon.nsigmaCutTOFKaMeson ;
142155 }
143156
144157 template <typename T>
145158 bool selectionPID2 (const T& candidate)
146159 {
147- if (!candidate.hasTOF () && std::abs (candidate.tpcNSigmaKa ()) < grpKaon.nsigmaCutTPCKaMeson ) {
148- return true ;
160+ const float nTPC = candidate.tpcNSigmaKa ();
161+
162+ // No TOF hit: TPC-only PID at all pT.
163+ if (!candidate.hasTOF ()) {
164+ return std::abs (nTPC) < grpKaon.nsigmaCutTPCKaMeson ;
149165 }
150- if (candidate.hasTOF () && candidate.beta () > grpKaon.cutTOFBetaKaMeson && std::sqrt (candidate.tpcNSigmaKa () * candidate.tpcNSigmaKa () + candidate.tofNSigmaKa () * candidate.tofNSigmaKa ()) < grpKaon.nsigmaCutTOFKaMeson ) {
151- return true ;
166+
167+ if (candidate.beta () <= grpKaon.cutTOFBetaKaMeson ) {
168+ return false ;
152169 }
153- return false ;
170+
171+ const float nTOF = candidate.tofNSigmaKa ();
172+ const float nCombined = std::sqrt (nTPC * nTPC + nTOF * nTOF);
173+
174+ return nCombined < grpKaon.nsigmaCutTOFKaMeson ;
154175 }
155176
156177 template <typename T>
157178 bool selectionPID3 (const T& candidate)
158179 {
159- constexpr float pSwitch = 0 .5f ;
160-
161180 const float pt = candidate.pt ();
162181 const float nTPC = candidate.tpcNSigmaKa ();
163182
164- if (pt < pSwitch && !candidate.hasTOF ()) {
183+ // Low pT: TPC-only. TOF is ignored even if present.
184+ if (pt < grpKaon.pSwitchPID ) {
165185 return std::abs (nTPC) < grpKaon.nsigmaCutTPCKaMeson ;
166186 }
167187
188+ // High pT: TOF is mandatory.
168189 if (!candidate.hasTOF ()) {
169190 return false ;
170191 }
171192
193+ if (candidate.beta () <= grpKaon.cutTOFBetaKaMeson ) {
194+ return false ;
195+ }
196+
172197 const float nTOF = candidate.tofNSigmaKa ();
173198 const float nCombined = std::sqrt (nTPC * nTPC + nTOF * nTOF);
174199
@@ -178,43 +203,191 @@ struct phiflow {
178203 template <typename T>
179204 bool selectionPID4 (const T& candidate)
180205 {
181- constexpr float pSwitch = 0 .5f ;
182-
183206 const float pt = candidate.pt ();
184207 const float nTPC = candidate.tpcNSigmaKa ();
185208
186- if (pt < pSwitch) {
209+ // Low pT: TPC-only. TOF is ignored even if present.
210+ if (pt < grpKaon.pSwitchPID ) {
187211 return std::abs (nTPC) < grpKaon.nsigmaCutTPCKaMeson ;
188212 }
189213
214+ // High pT: TOF is mandatory.
190215 if (!candidate.hasTOF ()) {
191216 return false ;
192217 }
193218
219+ if (candidate.beta () <= grpKaon.cutTOFBetaKaMeson ) {
220+ return false ;
221+ }
222+
194223 const float nTOF = candidate.tofNSigmaKa ();
195224
196225 return std::abs (nTPC) < grpKaon.nsigmaCutTPCKaMeson &&
197226 std::abs (nTOF) < grpKaon.nsigmaCutTOFKaMeson ;
198227 }
199228
200229 template <typename T>
201- uint8_t kaonPidMask (const T& trk )
230+ bool selectionPID5 (const T& candidate )
202231 {
203- uint8_t m = 0 ;
232+ // This matches the TOF-only selection from the other task.
233+ if (!candidate.hasTOF ()) {
234+ return false ;
235+ }
204236
205- if (selectionPID (trk) ) {
206- m |= kPID1 ;
237+ if (candidate. beta () <= grpKaon. cutTOFBetaKaMeson ) {
238+ return false ;
207239 }
208- if (selectionPID2 (trk)) {
209- m |= kPID2 ;
240+
241+ return std::abs (candidate.tofNSigmaKa ()) <
242+ grpKaon.nsigmaCutTOFKaMeson ;
243+ }
244+
245+ template <typename T>
246+ bool selectionPID6 (const T& candidate)
247+ {
248+ const float p = candidate.p ();
249+ const float nTPC = candidate.tpcNSigmaKa ();
250+
251+ // This follows selectionPIDpTdependent2 from the other task.
252+ // Note: it uses total momentum p, not transverse momentum pT.
253+ if (p < grpKaon.pSwitchAsymPID ) {
254+ return std::abs (nTPC) < grpKaon.nsigmaCutTPCKaMeson ;
255+ }
256+
257+ if (!candidate.hasTOF ()) {
258+ return false ;
210259 }
211- if (selectionPID3 (trk)) {
212- m |= kPID3 ;
260+
261+ if (std::abs (nTPC) >= grpKaon.nsigmaCutTPCKaMeson ) {
262+ return false ;
213263 }
214- if (selectionPID4 (trk)) {
215- m |= kPID4 ;
264+
265+ if (candidate.beta () <= grpKaon.cutTOFBetaKaMeson ) {
266+ return false ;
267+ }
268+
269+ const float nTOF = candidate.tofNSigmaKa ();
270+
271+ if (p < 1 .6f ) {
272+ return nTOF > -5 .0f && nTOF < 10 .0f ;
273+ }
274+
275+ if (p < 2 .0f ) {
276+ return nTOF > -3 .0f && nTOF < 10 .0f ;
277+ }
278+
279+ if (p < 2 .5f ) {
280+ return nTOF > -3 .0f && nTOF < 6 .0f ;
281+ }
282+
283+ if (p < 4 .0f ) {
284+ return nTOF > -2 .5f && nTOF < 4 .0f ;
285+ }
286+
287+ if (p < 5 .0f ) {
288+ return nTOF > -4 .0f && nTOF < 3 .0f ;
289+ }
290+
291+ if (p < 6 .0f ) {
292+ return nTOF > -4 .0f && nTOF < 2 .5f ;
216293 }
217- return m;
294+
295+ return nTOF > -3 .0f && nTOF < 3 .0f ;
296+ }
297+
298+ template <typename T>
299+ bool selectionPID7 (const T& candidate)
300+ {
301+ const float p = candidate.p ();
302+ const float nTPC = candidate.tpcNSigmaKa ();
303+
304+ // This follows selectionPID22 from the other task.
305+ // If TOF is disabled, use only the TPC kaon selection.
306+ if (!grpKaon.applyTOFAsymPID ) {
307+ return std::abs (nTPC) < grpKaon.nsigmaCutTPCKaMeson ;
308+ }
309+
310+ // No TOF hit: allow TPC-only PID at all momenta.
311+ if (!candidate.hasTOF ()) {
312+ return std::abs (nTPC) < grpKaon.nsigmaCutTPCKaMeson ;
313+ }
314+
315+ // For tracks with TOF, asymmetric TOF selection starts above p = 0.5.
316+ if (p <= 0 .5f ) {
317+ return false ;
318+ }
319+
320+ if (std::abs (nTPC) >= grpKaon.nsigmaCutTPCKaMeson ) {
321+ return false ;
322+ }
323+
324+ if (candidate.beta () <= grpKaon.cutTOFBetaKaMeson ) {
325+ return false ;
326+ }
327+
328+ const float nTOF = candidate.tofNSigmaKa ();
329+
330+ if (p < 1 .6f ) {
331+ return nTOF > -5 .0f && nTOF < 10 .0f ;
332+ }
333+
334+ if (p < 2 .0f ) {
335+ return nTOF > -3 .0f && nTOF < 10 .0f ;
336+ }
337+
338+ if (p < 2 .5f ) {
339+ return nTOF > -3 .0f && nTOF < 6 .0f ;
340+ }
341+
342+ if (p < 4 .0f ) {
343+ return nTOF > -2 .5f && nTOF < 4 .0f ;
344+ }
345+
346+ if (p < 5 .0f ) {
347+ return nTOF > -4 .0f && nTOF < 3 .0f ;
348+ }
349+
350+ if (p < 6 .0f ) {
351+ return nTOF > -4 .0f && nTOF < 2 .5f ;
352+ }
353+
354+ return nTOF > -3 .0f && nTOF < 3 .0f ;
355+ }
356+
357+ template <typename T>
358+ uint8_t kaonPidMask (const T& track)
359+ {
360+ uint8_t mask = 0 ;
361+
362+ if (selectionPID (track)) {
363+ mask |= kPID1 ;
364+ }
365+
366+ if (selectionPID2 (track)) {
367+ mask |= kPID2 ;
368+ }
369+
370+ if (selectionPID3 (track)) {
371+ mask |= kPID3 ;
372+ }
373+
374+ if (selectionPID4 (track)) {
375+ mask |= kPID4 ;
376+ }
377+
378+ if (selectionPID5 (track)) {
379+ mask |= kPID5 ;
380+ }
381+
382+ if (selectionPID6 (track)) {
383+ mask |= kPID6 ;
384+ }
385+
386+ if (selectionPID7 (track)) {
387+ mask |= kPID7 ;
388+ }
389+
390+ return mask;
218391 }
219392
220393 struct StoredKaon {
@@ -249,6 +422,12 @@ struct phiflow {
249422
250423 histos.fill (HIST (" hEvtSelInfo" ), 0.5 );
251424
425+ if (!collision.triggereventsp ()) {
426+ return ;
427+ }
428+
429+ histos.fill (HIST (" hEvtSelInfo" ), 1.5 );
430+
252431 if (!((!rctCut.requireRCTFlagChecker || rctChecker (collision)) &&
253432 collision.selection_bit (aod::evsel::kNoSameBunchPileup ) &&
254433 collision.selection_bit (aod::evsel::kIsGoodZvtxFT0vsPV ) &&
@@ -261,7 +440,8 @@ struct phiflow {
261440 return ;
262441 }
263442
264- histos.fill (HIST (" hEvtSelInfo" ), 1.5 );
443+ histos.fill (HIST (" hEvtSelInfo" ), 2.5 );
444+
265445 histos.fill (HIST (" hCent" ), centrality);
266446
267447 std::vector<StoredKaon> selectedKaons;
@@ -290,7 +470,7 @@ struct phiflow {
290470 const float nSigmaITS1 =
291471 itsResponse.nSigmaITS <o2::track::PID ::Kaon>(track1);
292472
293- if (grpKaon.itsPIDSelection &&
473+ if (grpKaon.itsPIDSelection && track1. p () < 1.0 &&
294474 (nSigmaITS1 <= grpKaon.lowITSPIDNsigma ||
295475 nSigmaITS1 >= grpKaon.highITSPIDNsigma )) {
296476 continue ;
@@ -327,7 +507,7 @@ struct phiflow {
327507 const float nSigmaITS2 =
328508 itsResponse.nSigmaITS <o2::track::PID ::Kaon>(track2);
329509
330- if (grpKaon.itsPIDSelection &&
510+ if (grpKaon.itsPIDSelection && track2. p () < 1.0 &&
331511 (nSigmaITS2 <= grpKaon.lowITSPIDNsigma ||
332512 nSigmaITS2 >= grpKaon.highITSPIDNsigma )) {
333513 continue ;
@@ -353,11 +533,13 @@ struct phiflow {
353533
354534 // No selected K+ or K- in this collision:
355535 // not writing a reduced event row.
536+ histos.fill (HIST (" hEvtSelInfo" ), 3.5 );
537+ /*
356538 if (selectedKaons.empty()) {
357539 return;
358540 }
359-
360- histos.fill (HIST (" hEvtSelInfo" ), 2 .5 );
541+ */
542+ histos.fill (HIST (" hEvtSelInfo" ), 4 .5 );
361543
362544 kaonEvent (centrality,
363545 vz,
0 commit comments