1313// / \brief D± → π± K∓ π± and D_s± → K± K∓ π± skimming with track-level ML
1414// / TEST ONLY, PLEASE DO NOT USE FOR ANALYSIS
1515// / \author Fabrizio Chinu <fabrizio.chinu@cern.ch>, Universita and INFN Torino
16+ // / \author Marcello Di Costanzo <marcello.di.costanzo@cern.ch>, Turin Polytechnic University and INFN Turin
1617
1718#include " PWGHF/Core/CentralityEstimation.h"
1819#include " PWGHF/Core/HfMlResponseHfTracks.h"
@@ -102,7 +103,9 @@ enum Channels3Prong {
102103 NChannels3Prong
103104};
104105
105- constexpr std::array<int , NChannels3Prong> DecayTypeOfChannel{
106+ constexpr std::array<int , NChannels2Prong> DecayTypeOfChannel2Prong{
107+ hf_cand_2prong::DecayType::D0ToPiK};
108+ constexpr std::array<int , NChannels3Prong> DecayTypeOfChannel3Prong{
106109 hf_cand_3prong::DecayType::DplusToPiKPi,
107110 hf_cand_3prong::DecayType::DsToKKPi};
108111
@@ -120,9 +123,6 @@ enum TrackMlRole {
120123 NTrackMlRoles
121124};
122125
123- constexpr std::array<int , NChannels3Prong> RolePionOfChannel{RolePionDplus, RolePionDs};
124- constexpr std::array<int , NChannels3Prong> RoleKaonOfChannel{RoleKaonDplus, RoleKaonDs};
125-
126126constexpr int N2Prongs = 2 ; // Number of prongs for 2-prong candidates
127127constexpr int N3Prongs = 3 ; // Number of prongs for 3-prong candidates
128128constexpr int NMassHypos = 2 ; // mass hypotheses per channel, i.e. the two orderings of the same-sign pair
@@ -150,7 +150,7 @@ constexpr TrackMlRole trackRoles3Prongs[NChannels3Prong][NMassHypos][N3Prongs] =
150150constexpr double PtMaxModel = 1 .e10 ;
151151
152152constexpr uint32_t MaskSameSignAny = (1u << RolePionD0) | (1u << RoleKaonD0) | (1u << RolePionDplus) | (1u << RolePionDs) | (1u << RoleKaonDs) | (1u << RoleSoftPiDstar);
153- constexpr uint32_t MaskOppSignAny = (1u << RolePionD0) | (1u << RoleKaonD0) | (1u << RoleKaonDplus) | (1u << RoleKaonDs);
153+ constexpr uint32_t MaskOppSignAny = (1u << RolePionD0) | (1u << RoleKaonD0) | (1u << RoleKaonDplus) | (1u << RoleKaonDs) | ( 1u << RoleSoftPiDstar) ;
154154
155155// / Where the combinatorics spends its time, accumulated in seconds into hTiming.
156156enum TimingStep {
@@ -1061,38 +1061,14 @@ struct HfMlBasedTrackSelector {
10611061 // / \param maskSame is the isIdentifiedPid mask of the first same-sign prong
10621062 static void checkCandidateAllowed (const uint32_t maskOpp, const uint32_t maskSame, bool & canBe2Prong, bool & canBe3Prong)
10631063 {
1064- canBe2Prong = TESTBIT (maskOpp, RoleKaonD0) && TESTBIT (maskSame, RolePionD0);
1064+ canBe2Prong = ( TESTBIT (maskOpp, RoleKaonD0) && TESTBIT (maskSame, RolePionD0)) || ( TESTBIT (maskOpp, RolePionD0) && TESTBIT (maskSame, RoleKaonD0) );
10651065 // For D* we check that we can have a D0 and later apply the selection for the soft pion
10661066
10671067 const bool okDplus = TESTBIT (maskOpp, RoleKaonDplus) && TESTBIT (maskSame, RolePionDplus);
10681068 const bool okDs = TESTBIT (maskOpp, RoleKaonDs) && (TESTBIT (maskSame, RoleKaonDs) || TESTBIT (maskSame, RolePionDs));
10691069 canBe3Prong = okDplus || okDs;
10701070 }
10711071
1072- // / Check whether the three ML masks can satisfy any mass hypothesis of either channel
1073- // / \param maskOpp is the mask of the opposite-sign prong (prong 1)
1074- // / \param mask1, mask2 are the masks of the same-sign prongs (prongs 0 and 2)
1075- static bool pairRoleOk (const uint32_t maskOpp, const uint32_t maskSame)
1076- {
1077- const std::array<uint32_t , N2Prongs> masks{maskSame, maskOpp};
1078- for (int iChannel = 0 ; iChannel < NChannels2Prong; iChannel++) {
1079- for (int iHypo = 0 ; iHypo < NMassHypos; iHypo++) {
1080- bool isHypoAlive = true ;
1081- for (int iProng = 0 ; iProng < N2Prongs; iProng++) {
1082- const int role = trackRoles2Prongs[iChannel][iHypo][iProng];
1083- if (!TESTBIT (masks[iProng], role)) {
1084- isHypoAlive = false ;
1085- break ;
1086- }
1087- }
1088- if (isHypoAlive) {
1089- return true ;
1090- }
1091- }
1092- }
1093- return false ;
1094- }
1095-
10961072 // / Check whether the three ML masks can satisfy any mass hypothesis of either channel
10971073 // / \param maskOpp is the mask of the opposite-sign prong (prong 1)
10981074 // / \param mask1, mask2 are the masks of the same-sign prongs (prongs 0 and 2)
@@ -1307,7 +1283,9 @@ struct HfMlBasedTrackSelector {
13071283 size_t nChannels = is3Prong ? static_cast <size_t >(NChannels3Prong) : static_cast <size_t >(NChannels2Prong);
13081284 for (size_t iChannel = 0 ; iChannel < nChannels; iChannel++) {
13091285 if (TESTBIT (isSelected, iChannel)) {
1310- SETBIT (hfFlag, DecayTypeOfChannel[iChannel]);
1286+ const int decayType = is3Prong ? DecayTypeOfChannel3Prong[iChannel]
1287+ : DecayTypeOfChannel2Prong[iChannel];
1288+ SETBIT (hfFlag, decayType);
13111289 }
13121290 }
13131291 return hfFlag;
@@ -1491,16 +1469,18 @@ struct HfMlBasedTrackSelector {
14911469
14921470 // / Reconstruct and preselect one 2-prong candidate, and fill its table row if it survives.
14931471 // / \param collision is the collision the candidate belongs to
1494- // / \param prong0,1 are the track informations
1472+ // / \param prongPos is the positive track information
1473+ // / \param prongNeg are the negative track information
14951474 template <typename TProngInfo>
14961475 void processPair (SelectedCollisions::iterator const & collision,
1497- TProngInfo const & prong0 , TProngInfo const & prong1 ,
1498- std::array<int , NChannels2Prong>& whichHypo2Prong)
1476+ TProngInfo const & prongPos , TProngInfo const & prongNeg ,
1477+ std::array<int , NChannels2Prong + 1 >& whichHypo2Prong)
14991478 {
15001479 uint32_t isSelected2ProngCand = BIT (NChannels2Prong) - 1 ;
15011480 whichHypo2Prong.fill (BIT (NMassHypos) - 1 ); // 2 bits on, all mass hypotheses alive
1481+ whichHypo2Prong[NChannels2Prong] = 0 ; // D0 for D*
15021482
1503- std::array<uint32_t , N2Prongs> isIdentifiedPid{prong0 .mask , prong1 .mask };
1483+ std::array<uint32_t , N2Prongs> isIdentifiedPid{prongPos .mask , prongNeg .mask };
15041484 applyMlRoleSelection (isIdentifiedPid, whichHypo2Prong, isSelected2ProngCand);
15051485 if (isSelected2ProngCand == 0 ) {
15061486 return ;
@@ -1516,15 +1496,15 @@ struct HfMlBasedTrackSelector {
15161496
15171497 // 2-prong selections
15181498 const std::array pvCoord{collision.posX (), collision.posY (), collision.posZ ()};
1519- applySelection2Prong (pVecCandProng2, prong0, prong1 , secondaryVertex2, pvCoord, whichHypo2Prong, isSelected2ProngCand);
1499+ applySelection2Prong (pVecCandProng2, prongPos, prongNeg , secondaryVertex2, pvCoord, whichHypo2Prong, isSelected2ProngCand);
15201500
15211501 // Only D0 for now
15221502 if (!TESTBIT (isSelected2ProngCand, ChannelD0ToPiK)) {
15231503 return ;
15241504 }
15251505
15261506 // fill table row
1527- rowTrackIndexProng2 (collision.globalIndex (), prong0 .globalIndex , prong1 .globalIndex , hfFlagOfSelection (isSelected2ProngCand, false ));
1507+ rowTrackIndexProng2 (collision.globalIndex (), prongPos .globalIndex , prongNeg .globalIndex , hfFlagOfSelection (isSelected2ProngCand, false ));
15281508 ++counters[CountPairsWritten];
15291509
15301510 // fill histograms
@@ -1653,8 +1633,8 @@ struct HfMlBasedTrackSelector {
16531633 for (const int iOpp : oppSignList) { // o2-linter: disable=const-ref-in-for-loop (int elements)
16541634 const auto & prongOpp = oppSignCache.prongs [iOpp];
16551635
1656- for (std::size_t i1 = 0 ; i1 < sameSignList.size (); ++i1 ) {
1657- const auto & prong1 = sameSignCache.prongs [sameSignList[i1 ]];
1636+ for (std::size_t iSame1 = 0 ; iSame1 < sameSignList.size (); ++iSame1 ) {
1637+ const auto & prong1 = sameSignCache.prongs [sameSignList[iSame1 ]];
16581638 ++counters[CountPairsSeen];
16591639 bool canBe2Prong{false }, canBe3Prong{false };
16601640 bool isTwoProngVtxGoodFor3Prongs{true };
@@ -1687,16 +1667,16 @@ struct HfMlBasedTrackSelector {
16871667 ++counters[CountPairsRejected2P];
16881668 continue ;
16891669 }
1670+ if (useTwoTrackVertex) {
1671+ isTwoProngVtxGoodFor3Prongs = isTwoTrackVertexSelectedFor3Prongs (df2.getPCACandidate (), pvCoord2Prong, df2);
1672+ }
16901673 if (store2Prongs || storeDstar) {
16911674 const auto tStartD0 = tickIf (doTiming);
16921675 processPair (collision, prong1, prongOpp, whichHypo2Prong);
16931676 if (doTiming) {
16941677 timing[TimeProcessD0] += elapsedSeconds (tStartD0);
16951678 }
16961679 }
1697- if (useTwoTrackVertex) {
1698- isTwoProngVtxGoodFor3Prongs = isTwoTrackVertexSelectedFor3Prongs (df2.getPCACandidate (), pvCoord2Prong, df2);
1699- }
17001680 }
17011681
17021682 // D* -> D0 pi+ candidates
@@ -1710,7 +1690,7 @@ struct HfMlBasedTrackSelector {
17101690 for (std::size_t iSoftPi = 0 ; iSoftPi < sameSignList.size (); ++iSoftPi) {
17111691 const auto & prongSoftPi = sameSignCache.prongs [sameSignList[iSoftPi]];
17121692
1713- if (iSoftPi == static_cast <std::size_t >(i1 )) {
1693+ if (iSoftPi == static_cast <std::size_t >(iSame1 )) {
17141694 continue ; // skip the same track
17151695 }
17161696 if (!TESTBIT (prongSoftPi.mask , RoleSoftPiDstar)) {
@@ -1737,7 +1717,7 @@ struct HfMlBasedTrackSelector {
17371717
17381718 // Update the index of the last filled D0 candidate
17391719 processDstar (collision, lastFilledD0, prongSoftPi.globalIndex ,
1740- prong1 .pVec , prongOpp .pVec , prongSoftPi.pVec );
1720+ prongOpp .pVec , prong1 .pVec , prongSoftPi.pVec );
17411721 }
17421722 }
17431723 }
@@ -1756,8 +1736,8 @@ struct HfMlBasedTrackSelector {
17561736 continue ;
17571737 }
17581738 // 3-prong candidates
1759- for (std::size_t i2 = i1 + 1 ; i2 < sameSignList.size (); ++i2 ) {
1760- const auto & prong2 = sameSignCache.prongs [sameSignList[i2 ]];
1739+ for (std::size_t iSame2 = iSame1 + 1 ; iSame2 < sameSignList.size (); ++iSame2 ) {
1740+ const auto & prong2 = sameSignCache.prongs [sameSignList[iSame2 ]];
17611741 if (!tripletRoleOk (prongOpp.mask , prong1.mask , prong2.mask )) {
17621742 continue ;
17631743 }
0 commit comments