3131#include < CCDB/BasicCCDBManager.h>
3232#include < CommonConstants/PhysicsConstants.h>
3333#include < Framework/ASoA.h>
34+ #include < Framework/ASoAHelpers.h>
3435#include < Framework/AnalysisDataModel.h>
3536#include < Framework/AnalysisHelpers.h>
3637#include < Framework/AnalysisTask.h>
4243#include < Framework/OutputObjHeader.h>
4344#include < Framework/runDataProcessing.h>
4445
45- #include < Math/Vector4D.h>
4646#include < Math/Vector4Dfwd.h>
4747#include < TH1.h>
48- #include < TList.h>
49- #include < TPDGCode.h>
5048
5149#include < cmath>
50+ #include < cstddef>
5251#include < string>
5352#include < vector>
5453
@@ -182,6 +181,14 @@ struct HResonanceCorrelationFilter {
182181 Configurable<float > assocPionNSigmaTPCFOF{" assocPionNSigmaTPCFOF" , 3 , " minimal n sigma in TOF and TPC for Pion ID" };
183182 Configurable<float > rejectSigma{" rejectSigma" , 1 , " n sigma for rejecting pion candidates" };
184183
184+ // Associated kaon identification (mirrors the pion selection above, with
185+ // the accept/reject roles swapped: accept kaon-consistent tracks, reject
186+ // pion-/proton-consistent ones). Selected via the Species template tag on
187+ // isValidAssocTrack<Species>() below -- production path (which table rows
188+ // get made) is still separate per process function, only the PID gate
189+ // logic itself is shared.
190+ Configurable<float > assocKaonNSigmaTPCFOF{" assocKaonNSigmaTPCFOF" , 3 , " minimal n sigma in TOF and TPC for Kaon ID" };
191+
185192 // primary particle DCAxy selections
186193 // formula: |DCAxy| < 0.004f + (0.013f / pt)
187194 Configurable<float > dcaXYconstant{" dcaXYconstant" , 0.004 , " [0] in |DCAxy| < [0]+[1]/pT" };
@@ -391,7 +398,7 @@ struct HResonanceCorrelationFilter {
391398
392399 // more event selections in Pb-Pb
393400 template <typename TCollision>
394- bool isCollisionSelectedPbPb (TCollision collision)
401+ bool isCollisionSelectedPbPb (TCollision const & collision)
395402 {
396403 if (!collision.selection_bit (aod::evsel::kIsTriggerTVX ) && eventSelections.requireGoodTriggerTVX ) /* FT0 vertex (acceptable FT0C-FT0A time difference) collisions */
397404 return false ;
@@ -626,7 +633,7 @@ struct HResonanceCorrelationFilter {
626633
627634 // reco-level trigger quality checks (N.B.: DCA is filtered, not selected)
628635 template <class TTrack >
629- bool isValidTrigger (TTrack track)
636+ bool isValidTrigger (TTrack const & track)
630637 {
631638 if (track.eta () > generalSelections.triggerEtaMax || track.eta () < generalSelections.triggerEtaMin ) {
632639 return false ;
@@ -650,9 +657,30 @@ struct HResonanceCorrelationFilter {
650657 return true ;
651658 }
652659
653- template <class TTrack >
654- bool isValidAssocTrack (TTrack assoc)
660+ // Species tag for isValidAssocTrack<Species>()'s PID gate below. AssocPion
661+ // and AssocKaon select which nSigma cut direction applies (accept that
662+ // species, reject the other two); AssocHadron carries no PID logic of its
663+ // own -- passed for clarity at Hadron call sites, but never actually reaches
664+ // the `if constexpr (Species == AssocKaon) ... else ...` branch, since the
665+ // outer `requires { assoc.tofSignal(); }` is already false for FullTracks
666+ // (Hadron's track type, which has no PID columns at all).
667+ enum AssocSpecies { AssocPion = 0 ,
668+ AssocKaon = 1 ,
669+ AssocHadron = 2 };
670+
671+ // Merged predicate for the Pion/Kaon/Hadron associated-track pools. Pion and
672+ // Kaon both run over IDTracks/IDTracksMC (identical C++ type), so the two
673+ // PID directions cannot be told apart by a `requires{}` type check the way
674+ // Hadron (FullTracks, no PID columns) is told apart from the other two --
675+ // hence the explicit non-type template parameter instead. Everything except
676+ // the PID nSigma cut direction (phase-space cuts, MC-truth lookup, table
677+ // fills) is identical across all three species, so it stays unduplicated
678+ // here; only the accept/reject block branches on Species.
679+ template <int Species, class TTrack >
680+ bool isValidAssocTrack (TTrack const & assoc)
655681 {
682+ static_assert (Species == AssocPion || Species == AssocKaon || Species == AssocHadron,
683+ " isValidAssocTrack: unknown species tag" );
656684 if (assoc.eta () > generalSelections.assocEtaMax || assoc.eta () < generalSelections.assocEtaMin ) {
657685 return false ;
658686 }
@@ -670,27 +698,49 @@ struct HResonanceCorrelationFilter {
670698 float nSigmaTPCTOF[8 ] = {-10 , -10 , -10 , -10 , -10 , -10 , -10 , -10 };
671699 if constexpr (requires { assoc.tofSignal (); } && !requires { assoc.mcParticle (); }) {
672700 if (assoc.tofSignal () > 0 ) {
673- if (std::sqrt (assoc.tofNSigmaPi () * assoc.tofNSigmaPi () + assoc.tpcNSigmaPi () * assoc.tpcNSigmaPi ()) > trackSelections.assocPionNSigmaTPCFOF )
674- return false ;
675- if (assoc.tofNSigmaPr () < trackSelections.rejectSigma )
676- return false ;
677- if (assoc.tpcNSigmaPr () < trackSelections.rejectSigma )
678- return false ;
679- if (assoc.tofNSigmaKa () < trackSelections.rejectSigma )
680- return false ;
681- if (assoc.tpcNSigmaKa () < trackSelections.rejectSigma )
682- return false ;
701+ if constexpr (Species == AssocKaon) {
702+ if (std::sqrt (assoc.tofNSigmaKa () * assoc.tofNSigmaKa () + assoc.tpcNSigmaKa () * assoc.tpcNSigmaKa ()) > trackSelections.assocKaonNSigmaTPCFOF )
703+ return false ;
704+ if (assoc.tofNSigmaPr () < trackSelections.rejectSigma )
705+ return false ;
706+ if (assoc.tpcNSigmaPr () < trackSelections.rejectSigma )
707+ return false ;
708+ if (assoc.tofNSigmaPi () < trackSelections.rejectSigma )
709+ return false ;
710+ if (assoc.tpcNSigmaPi () < trackSelections.rejectSigma )
711+ return false ;
712+ } else {
713+ if (std::sqrt (assoc.tofNSigmaPi () * assoc.tofNSigmaPi () + assoc.tpcNSigmaPi () * assoc.tpcNSigmaPi ()) > trackSelections.assocPionNSigmaTPCFOF )
714+ return false ;
715+ if (assoc.tofNSigmaPr () < trackSelections.rejectSigma )
716+ return false ;
717+ if (assoc.tpcNSigmaPr () < trackSelections.rejectSigma )
718+ return false ;
719+ if (assoc.tofNSigmaKa () < trackSelections.rejectSigma )
720+ return false ;
721+ if (assoc.tpcNSigmaKa () < trackSelections.rejectSigma )
722+ return false ;
723+ }
683724 nSigmaTPCTOF[4 ] = assoc.tofNSigmaPi ();
684725 nSigmaTPCTOF[5 ] = assoc.tofNSigmaKa ();
685726 nSigmaTPCTOF[6 ] = assoc.tofNSigmaPr ();
686727 nSigmaTPCTOF[7 ] = assoc.tofNSigmaEl ();
687728 } else {
688- if (assoc.tpcNSigmaPi () > trackSelections.assocPionNSigmaTPCFOF )
689- return false ;
690- if (assoc.tpcNSigmaPr () < trackSelections.rejectSigma )
691- return false ;
692- if (assoc.tpcNSigmaKa () < trackSelections.rejectSigma )
693- return false ;
729+ if constexpr (Species == AssocKaon) {
730+ if (assoc.tpcNSigmaKa () > trackSelections.assocKaonNSigmaTPCFOF )
731+ return false ;
732+ if (assoc.tpcNSigmaPr () < trackSelections.rejectSigma )
733+ return false ;
734+ if (assoc.tpcNSigmaPi () < trackSelections.rejectSigma )
735+ return false ;
736+ } else {
737+ if (assoc.tpcNSigmaPi () > trackSelections.assocPionNSigmaTPCFOF )
738+ return false ;
739+ if (assoc.tpcNSigmaPr () < trackSelections.rejectSigma )
740+ return false ;
741+ if (assoc.tpcNSigmaKa () < trackSelections.rejectSigma )
742+ return false ;
743+ }
694744 }
695745 nSigmaTPCTOF[0 ] = assoc.tpcNSigmaPi ();
696746 nSigmaTPCTOF[1 ] = assoc.tpcNSigmaKa ();
@@ -831,7 +881,7 @@ struct HResonanceCorrelationFilter {
831881 // / _________________________________________________
832882 // / Step 1: Populate table with trigger tracks
833883 for (auto const & track : tracks) {
834- if (!isValidAssocTrack (track))
884+ if (!isValidAssocTrack<AssocPion> (track))
835885 continue ;
836886 }
837887 }
@@ -859,7 +909,63 @@ struct HResonanceCorrelationFilter {
859909 // / _________________________________________________
860910 // / Step 1: Populate table with trigger tracks
861911 for (auto const & track : tracks) {
862- if (!isValidAssocTrack (track))
912+ if (!isValidAssocTrack<AssocPion>(track))
913+ continue ;
914+ }
915+ }
916+
917+ void processAssocKaons (soa::Join<aod::Collisions, aod::EvSels>::iterator const & collision, soa::Filtered<IDTracks> const & tracks, aod::BCsWithTimestamps const &)
918+ {
919+ // Load parameters for sideband subtraction
920+ auto bc = collision.bc_as <aod::BCsWithTimestamps>();
921+ // Perform basic event selection
922+ if (!collision.sel8 ()) {
923+ return ;
924+ }
925+ // No need to correlate stuff that's in far collisions
926+ if (std::abs (collision.posZ ()) > eventSelections.zVertexCut ) {
927+ return ;
928+ }
929+ if (zorroMask.value != " " ) {
930+ initCCDB (bc);
931+ bool zorroSelected = zorro.isSelected (collision.bc_as <aod::BCsWithTimestamps>().globalBC ()); // / Just let Zorro do the accounting
932+ if (!zorroSelected) {
933+ return ;
934+ }
935+ }
936+
937+ // / _________________________________________________
938+ // / Step 1: Populate table with trigger tracks
939+ for (auto const & track : tracks) {
940+ if (!isValidAssocTrack<AssocKaon>(track))
941+ continue ;
942+ }
943+ }
944+
945+ void processAssocKaonsMC (soa::Join<aod::Collisions, aod::EvSels>::iterator const & collision, soa::Filtered<IDTracksMC> const & tracks, aod::McParticles const &, aod::BCsWithTimestamps const &)
946+ {
947+ // Load parameters for sideband subtraction
948+ auto bc = collision.bc_as <aod::BCsWithTimestamps>();
949+ // Perform basic event selection
950+ if (!collision.sel8 ()) {
951+ return ;
952+ }
953+ // No need to correlate stuff that's in far collisions
954+ if (std::abs (collision.posZ ()) > eventSelections.zVertexCut ) {
955+ return ;
956+ }
957+ if (zorroMask.value != " " ) {
958+ initCCDB (bc);
959+ bool zorroSelected = zorro.isSelected (collision.bc_as <aod::BCsWithTimestamps>().globalBC ()); // / Just let Zorro do the accounting
960+ if (!zorroSelected) {
961+ return ;
962+ }
963+ }
964+
965+ // / _________________________________________________
966+ // / Step 1: Populate table with trigger tracks
967+ for (auto const & track : tracks) {
968+ if (!isValidAssocTrack<AssocKaon>(track))
863969 continue ;
864970 }
865971 }
@@ -887,7 +993,7 @@ struct HResonanceCorrelationFilter {
887993 // / _________________________________________________
888994 // / Step 1: Populate table with trigger tracks
889995 for (auto const & track : tracks) {
890- if (!isValidAssocTrack (track))
996+ if (!isValidAssocTrack<AssocHadron> (track))
891997 continue ;
892998 }
893999 }
@@ -914,7 +1020,7 @@ struct HResonanceCorrelationFilter {
9141020 // / _________________________________________________
9151021 // / Step 1: Populate table with trigger tracks
9161022 for (auto const & track : tracks) {
917- if (!isValidAssocTrack (track))
1023+ if (!isValidAssocTrack<AssocHadron> (track))
9181024 continue ;
9191025 }
9201026 }
@@ -1256,9 +1362,9 @@ struct HResonanceCorrelationFilter {
12561362 }
12571363
12581364 LorentzVectorPtEtaPhiMass kaon = LorentzVectorPtEtaPhiMass (kaonTrack.pt (), kaonTrack.eta (), kaonTrack.phi (),
1259- o2::constants::physics::MassKPlus);
1365+ o2::constants::physics::MassKPlus);
12601366 LorentzVectorPtEtaPhiMass pion = LorentzVectorPtEtaPhiMass (pionTrack.pt (), pionTrack.eta (), pionTrack.phi (),
1261- o2::constants::physics::MassPiPlus);
1367+ o2::constants::physics::MassPiPlus);
12621368 LorentzVectorPtEtaPhiMass kstar = kaon + pion;
12631369
12641370 float invMass = kstar.M ();
@@ -1326,6 +1432,8 @@ struct HResonanceCorrelationFilter {
13261432 PROCESS_SWITCH (HResonanceCorrelationFilter, processTriggersMC, " Produce trigger tables for MC" , false );
13271433 PROCESS_SWITCH (HResonanceCorrelationFilter, processAssocPions, " Produce associated Pion tables" , false );
13281434 PROCESS_SWITCH (HResonanceCorrelationFilter, processAssocPionsMC, " Produce associated Pion tables for MC" , false );
1435+ PROCESS_SWITCH (HResonanceCorrelationFilter, processAssocKaons, " Produce associated Kaon tables" , false );
1436+ PROCESS_SWITCH (HResonanceCorrelationFilter, processAssocKaonsMC, " Produce associated Kaon tables for MC" , false );
13291437 PROCESS_SWITCH (HResonanceCorrelationFilter, processAssocHadrons, " Produce associated Hadron tables" , true );
13301438 PROCESS_SWITCH (HResonanceCorrelationFilter, processAssocHadronsMC, " Produce associated Hadron tables for MC" , false );
13311439 PROCESS_SWITCH (HResonanceCorrelationFilter, processPhis, " Produce associated phi tables" , true );
0 commit comments