@@ -123,6 +123,9 @@ struct decay3bodyBuilder {
123123 Configurable<bool > doVertexQA{" doVertexQA" , false , " Flag to fill QA histograms for PV of (selected) events." };
124124 Configurable<bool > disableITSROFCut{" disableITSROFCut" , false , " Disable ITS ROF border cut" };
125125
126+ // MC processing options
127+ Configurable<bool > doStoreMcBkg{" doStoreMcBkg" , false , " Flag to store candidates which were not matched to true H3L/Anti-H3L decaying via three-body decay in MC (i.e. MC background) in the output table" };
128+
126129 // data processing options
127130 Configurable<bool > doSkimmedProcessing{" doSkimmedProcessing" , false , " Apply Zoroo counting in case of skimmed data input" };
128131 Configurable<std::string> triggerList{"triggerList", "fTriggerEventF1Proton, fTrackedOmega, fTrackedXi, fOmegaLargeRadius, fDoubleOmega, fOmegaHighMult, fSingleXiYN, fQuadrupleXi, fDoubleXi, fhadronOmega, fOmegaXi, fTripleXi, fOmega, fGammaVeryLowPtEMCAL, fGammaVeryLowPtDCAL, fGammaHighPtEMCAL, fGammaLowPtEMCAL, fGammaVeryHighPtDCAL, fGammaVeryHighPtEMCAL, fGammaLowPtDCAL, fJetNeutralLowPt, fJetNeutralHighPt, fGammaHighPtDCAL, fJetFullLowPt, fJetFullHighPt, fEMCALReadout, fPCMandEE, fPHOSnbar, fPCMHighPtPhoton, fPHOSPhoton, fLD, fPPPHI, fPD, fLLL, fPLL, fPPL, fPPP, fLeadingPtTrack, fHighFt0cFv0Flat, fHighFt0cFv0Mult, fHighFt0Flat, fHighFt0Mult, fHighMultFv0, fHighTrackMult, fHfSingleNonPromptCharm3P, fHfSingleNonPromptCharm2P, fHfSingleCharm3P, fHfPhotonCharm3P, fHfHighPt2P, fHfSigmaC0K0, fHfDoubleCharm2P, fHfBeauty3P, fHfFemto3P, fHfFemto2P, fHfHighPt3P, fHfSigmaCPPK, fHfDoubleCharm3P, fHfDoubleCharmMix, fHfPhotonCharm2P, fHfV0Charm2P, fHfBeauty4P, fHfV0Charm3P, fHfSingleCharm2P, fHfCharmBarToXiBach, fSingleMuHigh, fSingleMuLow, fLMeeHMR, fDiMuon, fDiElectron, fLMeeIMR, fSingleE, fTrackHighPt, fTrackLowPt, fJetChHighPt, fJetChLowPt, fUDdiffLarge, fUDdiffSmall, fITSextremeIonisation, fITSmildIonisation, fH3L3Body, fHe, fH2", "List of triggers used to select events"};
@@ -794,47 +797,56 @@ struct decay3bodyBuilder {
794797
795798 // check if daughters have MC particle
796799 if (!trackProton.has_mcParticle () || !trackPion.has_mcParticle () || !trackDeuteron.has_mcParticle ()) {
797- continue ;
798- }
800+ if (!doStoreMcBkg) {
801+ continue ; // if not storing MC background, skip candidates where at least one daughter is not matched to MC particle
802+ } else {
803+ this3BodyMCInfo.label = -5 ; // at least one non-matched daughter
804+ // fill analysis table (only McVtx3BodyDatas is filled here)
805+ fillAnalysisTables ();
806+ }
807+ } else { // all daughters are matched to MC particles, get their MC info
808+ // get MC daughter particles
809+ auto mcTrackProton = trackProton.template mcParticle_as <aod::McParticles>();
810+ auto mcTrackPion = trackPion.template mcParticle_as <aod::McParticles>();
811+ auto mcTrackDeuteron = trackDeuteron.template mcParticle_as <aod::McParticles>();
812+
813+ // set daughter MC info (also for non-matched mothers)
814+ this3BodyMCInfo.daughterPrPdgCode = mcTrackProton.pdgCode ();
815+ this3BodyMCInfo.daughterPiPdgCode = mcTrackPion.pdgCode ();
816+ this3BodyMCInfo.daughterDePdgCode = mcTrackDeuteron.pdgCode ();
817+ this3BodyMCInfo.isDeuteronPrimary = mcTrackDeuteron.isPhysicalPrimary ();
818+ this3BodyMCInfo.genMomProton = mcTrackProton.p ();
819+ this3BodyMCInfo.genMomPion = mcTrackPion.p ();
820+ this3BodyMCInfo.genMomDeuteron = mcTrackDeuteron.p ();
821+ this3BodyMCInfo.genPtProton = mcTrackProton.pt ();
822+ this3BodyMCInfo.genPtPion = mcTrackPion.pt ();
823+ this3BodyMCInfo.genPtDeuteron = mcTrackDeuteron.pt ();
824+
825+ // daughters are matched to MC, now we check if reco mother is true H3L/Anti-H3l and decayed via three-body decay
826+ this3BodyMCInfo.label = checkH3LTruth (mcTrackProton, mcTrackPion, mcTrackDeuteron); // returns global index of mother if true H3L/Anti-H3L mother decaying via three-body decay, otherwise negative value
827+
828+ // if not storing MC background, skip candidates where mother is not true H3L/Anti-H3L decaying via three-body decay
829+ if (!doStoreMcBkg && this3BodyMCInfo.label <= 0 ) {
830+ continue ;
831+ }
799832
800- // get MC daughter particles
801- auto mcTrackProton = trackProton.template mcParticle_as <aod::McParticles>();
802- auto mcTrackPion = trackPion.template mcParticle_as <aod::McParticles>();
803- auto mcTrackDeuteron = trackDeuteron.template mcParticle_as <aod::McParticles>();
804-
805- // set daughter MC info (also for non-matched candidates)
806- this3BodyMCInfo.daughterPrPdgCode = mcTrackProton.pdgCode ();
807- this3BodyMCInfo.daughterPiPdgCode = mcTrackPion.pdgCode ();
808- this3BodyMCInfo.daughterDePdgCode = mcTrackDeuteron.pdgCode ();
809- this3BodyMCInfo.isDeuteronPrimary = mcTrackDeuteron.isPhysicalPrimary ();
810- this3BodyMCInfo.genMomProton = mcTrackProton.p ();
811- this3BodyMCInfo.genMomPion = mcTrackPion.p ();
812- this3BodyMCInfo.genMomDeuteron = mcTrackDeuteron.p ();
813- this3BodyMCInfo.genPtProton = mcTrackProton.pt ();
814- this3BodyMCInfo.genPtPion = mcTrackPion.pt ();
815- this3BodyMCInfo.genPtDeuteron = mcTrackDeuteron.pt ();
816-
817- // check if reco mother is true H3L/Anti-H3l
818- bool isMuonReco;
819- int motherID = checkH3LTruth (mcTrackProton, mcTrackPion, mcTrackDeuteron, isMuonReco);
820-
821- // get generated mother MC info
822- if (motherID > 0 ) {
823- auto mcTrackH3L = mcParticles.rawIteratorAt (motherID);
824- this3BodyMCInfo.motherPdgCode = mcTrackH3L.pdgCode ();
825- this3BodyMCInfo.label = motherID;
826- this3BodyMCInfo.genMomentum = {mcTrackH3L.px (), mcTrackH3L.py (), mcTrackH3L.pz ()};
827- this3BodyMCInfo.genDecVtx = {mcTrackProton.vx (), mcTrackProton.vy (), mcTrackProton.vz ()};
828- this3BodyMCInfo.genCt = RecoDecay::sqrtSumOfSquares (mcTrackProton.vx () - mcTrackH3L.vx (), mcTrackProton.vy () - mcTrackH3L.vy (), mcTrackProton.vz () - mcTrackH3L.vz ()) * o2::constants::physics::MassHyperTriton / mcTrackH3L.p ();
829- this3BodyMCInfo.genPhi = mcTrackH3L.phi ();
830- this3BodyMCInfo.genEta = mcTrackH3L.eta ();
831- this3BodyMCInfo.genRapidity = mcTrackH3L.y ();
832- this3BodyMCInfo.isTrueH3L = this3BodyMCInfo.motherPdgCode > 0 ? true : false ;
833- this3BodyMCInfo.isTrueAntiH3L = this3BodyMCInfo.motherPdgCode < 0 ? true : false ;
834- }
833+ // get generated mother MC info for matched candidates
834+ if (this3BodyMCInfo.label > -1 ) {
835+ auto mcTrackH3L = mcParticles.rawIteratorAt (this3BodyMCInfo.label );
836+ this3BodyMCInfo.motherPdgCode = mcTrackH3L.pdgCode ();
837+ this3BodyMCInfo.genMomentum = {mcTrackH3L.px (), mcTrackH3L.py (), mcTrackH3L.pz ()};
838+ this3BodyMCInfo.genDecVtx = {mcTrackProton.vx (), mcTrackProton.vy (), mcTrackProton.vz ()};
839+ this3BodyMCInfo.genCt = RecoDecay::sqrtSumOfSquares (mcTrackProton.vx () - mcTrackH3L.vx (), mcTrackProton.vy () - mcTrackH3L.vy (), mcTrackProton.vz () - mcTrackH3L.vz ()) * o2::constants::physics::MassHyperTriton / mcTrackH3L.p ();
840+ this3BodyMCInfo.genPhi = mcTrackH3L.phi ();
841+ this3BodyMCInfo.genEta = mcTrackH3L.eta ();
842+ this3BodyMCInfo.genRapidity = mcTrackH3L.y ();
843+ this3BodyMCInfo.isTrueH3L = this3BodyMCInfo.motherPdgCode > 0 ? true : false ;
844+ this3BodyMCInfo.isTrueAntiH3L = this3BodyMCInfo.motherPdgCode < 0 ? true : false ;
845+ }
835846
836- // fill analysis tables (only McVtx3BodyDatas is filled here)
837- fillAnalysisTables ();
847+ // fill analysis tables (only McVtx3BodyDatas is filled here)
848+ fillAnalysisTables ();
849+ } // end of check if daughters have MC particle
838850
839851 // mark mcParticle as reconstructed
840852 if (this3BodyMCInfo.label > -1 ) {
@@ -1179,45 +1191,69 @@ struct decay3bodyBuilder {
11791191 // ______________________________________________________________
11801192 // function to check if a reconstructed mother is a true H3L/Anti-H3L (returns -1 if not)
11811193 template <typename MCTrack3B>
1182- int checkH3LTruth (MCTrack3B const & mcParticlePr, MCTrack3B const & mcParticlePi, MCTrack3B const & mcParticleDe, bool & isMuonReco )
1194+ int checkH3LTruth (MCTrack3B const & mcParticlePr, MCTrack3B const & mcParticlePi, MCTrack3B const & mcParticleDe)
11831195 {
1184- if (std::abs (mcParticlePr.pdgCode ()) != PDG_t::kProton || std::abs (mcParticleDe.pdgCode ()) != o2::constants::physics::Pdg::kDeuteron ) {
1185- return -1 ;
1186- }
1187- // check proton and deuteron mother
1188- int prDeMomID = -1 ;
1189- for (const auto & motherPr : mcParticlePr.template mothers_as <aod::McParticles>()) {
1190- for (const auto & motherDe : mcParticleDe.template mothers_as <aod::McParticles>()) {
1191- if (motherPr.globalIndex () == motherDe.globalIndex () && std::abs (motherPr.pdgCode ()) == o2::constants::physics::Pdg::kHyperTriton ) {
1192- prDeMomID = motherPr.globalIndex ();
1193- break ;
1194- }
1195- }
1196- }
1197- if (prDeMomID == -1 ) {
1198- return -1 ;
1199- }
1200- if (std::abs (mcParticlePi.pdgCode ()) != PDG_t::kPiPlus && std::abs (mcParticlePi.pdgCode ()) != PDG_t::kMuonMinus ) {
1201- return -1 ;
1196+ // return legend
1197+ // -4: proton, pion, or deuteron have wrong identity
1198+ // -3: proton and pion have a common mother which is a Lambda (i.e., not a direct daughter of hypertriton)
1199+ // -2: proton, pion, and deuteron don't have a common mother
1200+ // -1: proton, pion, and deuteron have common mother but it's NOT a hypertriton
1201+ // global mother ID: proton, pion, and deuteron have common mother and it's a hypertriton
1202+
1203+ // first, check identity of MC daughters
1204+ if (std::abs (mcParticlePr.pdgCode ()) != PDG_t::kProton || std::abs (mcParticleDe.pdgCode ()) != o2::constants::physics::Pdg::kDeuteron || (std::abs (mcParticlePi.pdgCode ()) != PDG_t::kPiPlus && std::abs (mcParticlePi.pdgCode ()) != PDG_t::kMuonMinus )) {
1205+ return -4 ;
12021206 }
12031207 // check if the pion track is a muon coming from a pi -> mu + vu decay, if yes, take the mother pi
12041208 auto mcParticlePiTmp = mcParticlePi;
12051209 if (std::abs (mcParticlePiTmp.pdgCode ()) == PDG_t::kMuonMinus ) {
1210+ bool isMuonReco = false ;
12061211 for (const auto & motherPi : mcParticlePiTmp.template mothers_as <aod::McParticles>()) {
12071212 if (std::abs (motherPi.pdgCode ()) == PDG_t::kPiPlus ) {
12081213 mcParticlePiTmp = motherPi;
12091214 isMuonReco = true ;
12101215 break ;
12111216 }
12121217 }
1218+ // If the track is a muon but none of its mothers is a pi+, treat as wrong identity
1219+ if (!isMuonReco) {
1220+ return -4 ;
1221+ }
12131222 }
1214- // now loop over the pion mother
1215- for (const auto & motherPi : mcParticlePiTmp.template mothers_as <aod::McParticles>()) {
1216- if (motherPi.globalIndex () == prDeMomID) {
1217- return motherPi.globalIndex ();
1223+
1224+ // now first check if the proton and pion have the same mother and it is a Lambda
1225+ for (const auto & motherPr : mcParticlePr.template mothers_as <aod::McParticles>()) {
1226+ for (const auto & motherPi : mcParticlePiTmp.template mothers_as <aod::McParticles>()) {
1227+ if (motherPr.globalIndex () == motherPi.globalIndex () && std::abs (motherPr.pdgCode ()) == PDG_t::kLambda ) {
1228+ return -3 ;
1229+ }
12181230 }
12191231 }
1220- return -1 ;
1232+
1233+ // now check if all three daughters have the same mother
1234+ int momID = -1 ;
1235+ int momPdgCode = 0 ;
1236+ for (const auto & motherPr : mcParticlePr.template mothers_as <aod::McParticles>()) {
1237+ for (const auto & motherDe : mcParticleDe.template mothers_as <aod::McParticles>()) {
1238+ for (const auto & motherPi : mcParticlePiTmp.template mothers_as <aod::McParticles>()) {
1239+ if (motherPr.globalIndex () == motherDe.globalIndex () && motherPr.globalIndex () == motherPi.globalIndex ()) {
1240+ momID = motherPr.globalIndex ();
1241+ momPdgCode = motherPr.pdgCode ();
1242+ break ;
1243+ }
1244+ }
1245+ }
1246+ }
1247+ if (momID == -1 ) {
1248+ return -2 ;
1249+ }
1250+
1251+ // check if the common mother is a hypertriton
1252+ if (std::abs (momPdgCode) == o2::constants::physics::Pdg::kHyperTriton ) {
1253+ return momID;
1254+ } else {
1255+ return -1 ; // common mother found but not a hypertriton
1256+ }
12211257 }
12221258
12231259 // ______________________________________________________________
0 commit comments