@@ -137,6 +137,24 @@ struct HfProducerCharmHadronsTrackFemtoDream {
137137
138138 // Configurable<bool> isForceGRP{"isForceGRP", false, "Set true if the magnetic field configuration is not available in the usual CCDB directory (e.g. for Run 2 converted data or unanchorad Monte Carlo)"};
139139
140+ // -------------------------
141+ // Kaon PID cut parameters
142+ // -------------------------
143+ struct : ConfigurableGroup {
144+ Configurable<float > pTrackMethod1Max{" pTrackMethod1Max" , 0 .85f , " Kaon PID Method1 (TPC-only): maximum p (GeV/c)" };
145+ Configurable<float > pTrackExcludeMin{" pTrackExcludeMin" , 0 .50f , " Kaon PID Method1: excluded p window minimum (GeV/c)" };
146+ Configurable<float > pTrackExcludeMax{" pTrackExcludeMax" , 0 .65f , " Kaon PID Method1: excluded p window maximum (GeV/c)" };
147+ Configurable<float > pTrackPiRejMin{" pTrackPiRejMin" , 0 .50f , " Kaon PID Method1: pion rejection active for p > this (GeV/c)" };
148+ Configurable<float > pTrackElRejMin{" pTrackElRejMin" , 0 .30f , " Kaon PID Method1: electron rejection active for p > this (GeV/c)" };
149+ Configurable<float > pTrackTightMin{" pTrackTightMin" , 1 .20f , " Kaon PID Method2 (TPC+TOF): tighten cuts for p > this (GeV/c)" };
150+ Configurable<float > nSigmaTpcKaMax{" nSigmaTpcKaMax" , 3 .f , " Kaon PID Method1: require |nSigmaTpcKa| < this" };
151+ Configurable<float > nSigmaTpcPiMin{" nSigmaTpcPiMin" , 3 .f , " Kaon PID Method1: require |nSigmaTpcPi| > this (pion)" };
152+ Configurable<float > nSigmaTpcElMin{" nSigmaTpcElMin" , 3 .f , " Kaon PID Method1: require |nSigmaTpcEl| > this (electron)" };
153+ Configurable<float > nSigmaCombKaMax{" nSigmaCombKaMax" , 3 .f , " Kaon PID Method2: require |nSigmaCombKa| < this" };
154+ Configurable<float > nSigmaCombKaTightMax{" nSigmaCombKaTightMax" , 2 .f , " Kaon PID Method2: for p > pTrackTightMin require |nSigmaCombKa| < this" };
155+ Configurable<float > nSigmaCombPiMax{" nSigmaCombPiMax" , 6 .f , " Kaon PID Method2: for p > pTrackTightMin require |nSigmaCombPi| < this" };
156+ } kaonPidSel;
157+
140158 Configurable<bool > isDebug{" isDebug" , true , " Enable Debug tables" };
141159 Configurable<bool > isRun3{" isRun3" , true , " Running on Run3 or pilot" };
142160
@@ -203,7 +221,7 @@ struct HfProducerCharmHadronsTrackFemtoDream {
203221 using FemtoFullCollisionMc = soa::Join<aod::Collisions, aod::EvSels, aod::Mults, aod::CentFT0Ms, aod::McCollisionLabels>::iterator;
204222 using FemtoFullMcgenCollisions = soa::Join<aod::McCollisions, o2::aod::MultsExtraMC>;
205223 using FemtoFullMcgenCollision = FemtoFullMcgenCollisions::iterator;
206- using FemtoHFTracks = soa::Join<aod::FullTracks, aod::TracksDCA, aod::pidTPCFullPi, aod::pidTPCFullKa, aod::pidTPCFullPr, aod::pidTPCFullDe, aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr, aod::pidTOFFullDe, aod::TracksPidPi, aod::PidTpcTofFullPi, aod::TracksPidKa, aod::PidTpcTofFullKa, aod::TracksPidPr, aod::PidTpcTofFullPr>;
224+ using FemtoHFTracks = soa::Join<aod::FullTracks, aod::TracksDCA, aod::pidTPCFullEl, aod:: pidTPCFullPi, aod::pidTPCFullKa, aod::pidTPCFullPr, aod::pidTPCFullDe, aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr, aod::pidTOFFullDe, aod::TracksPidPi, aod::PidTpcTofFullPi, aod::TracksPidKa, aod::PidTpcTofFullKa, aod::TracksPidPr, aod::PidTpcTofFullPr>;
207225 using FemtoHFTrack = FemtoHFTracks::iterator;
208226 using FemtoHFMcTracks = soa::Join<aod::McTrackLabels, FemtoHFTracks>;
209227 using FemtoHFMcTrack = FemtoHFMcTracks::iterator;
@@ -336,6 +354,64 @@ struct HfProducerCharmHadronsTrackFemtoDream {
336354 }
337355 }
338356
357+ // -------------------------
358+ // Kaon PID selection
359+ // -------------------------
360+ template <typename TrackType>
361+ bool isTrackKaonPidSelected (const TrackType& track)
362+ {
363+ const float pTrack = track.p ();
364+
365+ // =========================
366+ // Method 1: Tpc-only
367+ // =========================
368+ bool isTrackKaonPidMethod1 = true ;
369+
370+ if (pTrack >= kaonPidSel.pTrackMethod1Max ) {
371+ isTrackKaonPidMethod1 = false ;
372+ }
373+ if (std::abs (track.tpcNSigmaKa ()) >= kaonPidSel.nSigmaTpcKaMax ) {
374+ isTrackKaonPidMethod1 = false ;
375+ }
376+ if (pTrack >= kaonPidSel.pTrackExcludeMin && pTrack <= kaonPidSel.pTrackExcludeMax ) {
377+ isTrackKaonPidMethod1 = false ;
378+ }
379+ if (pTrack > kaonPidSel.pTrackPiRejMin && std::abs (track.tpcNSigmaPi ()) <= kaonPidSel.nSigmaTpcPiMin ) {
380+ isTrackKaonPidMethod1 = false ;
381+ }
382+ if (pTrack > kaonPidSel.pTrackElRejMin && std::abs (track.tpcNSigmaEl ()) <= kaonPidSel.nSigmaTpcElMin ) {
383+ isTrackKaonPidMethod1 = false ;
384+ }
385+
386+ // =========================
387+ // Method 2: Tpc+Tof combined
388+ // =========================
389+ bool isTrackKaonPidMethod2 = true ;
390+
391+ if (pTrack > kaonPidSel.pTrackMethod1Max && !track.hasTOF ()) {
392+ isTrackKaonPidMethod2 = false ;
393+ }
394+
395+ const float nSigmaCombKa = std::hypot (track.tpcNSigmaKa (), track.tofNSigmaKa ());
396+ const float nSigmaCombPi = std::hypot (track.tpcNSigmaPi (), track.tofNSigmaPi ());
397+
398+ if (std::abs (nSigmaCombKa) >= kaonPidSel.nSigmaCombKaMax ) {
399+ isTrackKaonPidMethod2 = false ;
400+ }
401+
402+ if (pTrack > kaonPidSel.pTrackTightMin ) {
403+ if (std::abs (nSigmaCombKa) >= kaonPidSel.nSigmaCombKaTightMax ) {
404+ isTrackKaonPidMethod2 = false ;
405+ }
406+ if (std::abs (nSigmaCombPi) >= kaonPidSel.nSigmaCombPiMax ) {
407+ isTrackKaonPidMethod2 = false ;
408+ }
409+ }
410+
411+ // OR between the two PID methods
412+ return isTrackKaonPidMethod1 || isTrackKaonPidMethod2;
413+ }
414+
339415 // / Function to retrieve the nominal magnetic field in kG (0.1T) and convert it directly to T
340416 void getMagneticFieldTesla (const aod::BCsWithTimestamps::iterator& bc)
341417 {
@@ -472,14 +548,28 @@ struct HfProducerCharmHadronsTrackFemtoDream {
472548 outputPartsTime (timeStamp);
473549 // now the table is filled
474550
475- outputParts (outputCollision.lastIndex (),
476- track.pt (),
477- track.eta (),
478- track.phi (),
479- aod::femtodreamparticle::ParticleType::kTrack ,
480- cutContainer.at (femtoDreamTrackSelection::TrackContainerPosition::kCuts ),
481- cutContainer.at (femtoDreamTrackSelection::TrackContainerPosition::kPID ),
482- track.dcaXY (), childIDs, 0 , 0 );
551+ if (trkPDGCode == kKPlus ) {
552+ const auto pidTrackPassBit = static_cast <aod::femtodreamparticle::cutContainerType>(isTrackKaonPidSelected (track));
553+
554+ outputParts (outputCollision.lastIndex (),
555+ track.pt (),
556+ track.eta (),
557+ track.phi (),
558+ aod::femtodreamparticle::ParticleType::kTrack ,
559+ cutContainer.at (femtoDreamTrackSelection::TrackContainerPosition::kCuts ),
560+ pidTrackPassBit,
561+ track.dcaXY (), childIDs, 0 , 0 );
562+ } else {
563+ outputParts (outputCollision.lastIndex (),
564+ track.pt (),
565+ track.eta (),
566+ track.phi (),
567+ aod::femtodreamparticle::ParticleType::kTrack ,
568+ cutContainer.at (femtoDreamTrackSelection::TrackContainerPosition::kCuts ),
569+ cutContainer.at (femtoDreamTrackSelection::TrackContainerPosition::kPID ),
570+ track.dcaXY (), childIDs, 0 , 0 );
571+ }
572+
483573 fIsTrackFilled = true ;
484574 // tmpIDtrack.push_back(track.globalIndex());
485575 if (isDebug.value ) {
0 commit comments