diff --git a/PWGHF/Core/DecayChannels.h b/PWGHF/Core/DecayChannels.h index 9e2f779cc2b..abc8ac291a6 100644 --- a/PWGHF/Core/DecayChannels.h +++ b/PWGHF/Core/DecayChannels.h @@ -219,6 +219,40 @@ enum DecayChannelToJpsiResonant : int8_t { NChannelsToJpsiResonant = BsToJpsiPhi // last channel }; } // namespace hf_cand_beauty + +namespace hf_cand_reso +{ +/// @brief resonance candidates: main channels +enum DecayChannelMain : int8_t { + // D1(2420)0 + D1zeroToDstarPi = 1, // D*+ π- + // D2*(2460)0 + D2starzeroToDplusPi = 2, // D+ π− + D2starzeroToDstarPi = 3, // D*+ π- + // D2*(2460)+ + D2starplusToD0Pi = 4, // D0 π+ + // Ds1(2536)+ + Ds1ToDstarK0s = 5, // D*+ K0s + // Ds2*(2573)+ + Ds2starToD0Kplus = 6, // D0 K+ + Ds2starToDplusK0s = 7, // D+ K0s + Ds2starToDstarK0s = 8, // D*+ K0s + // Ds1*(2700)+ + Ds1star2700ToDstarK0s = 9, // D*+ K0s + // Ds1*(2860)+ + Ds1star2860ToDstarK0s = 10, // D*+ K0s + // Ds3*(2860)+ + Ds3star2860ToDstarK0s = 11, // D*+ K0s + // Xic(3055)0 + Xic3055zeroToD0Lambda = 12, // D0 Λ + // Xic(3055)+ + Xic3055plusToDplusLambda = 13, // D+ Λ + // Xic(3080)0 + Xic3080zeroToD0Lambda = 14, // D0 Λ + // Xic(3080)+ + Xic3080plusToDplusLambda = 15 // D+ Λ +}; +} // namespace hf_cand_reso } // namespace o2::hf_decay #endif // PWGHF_CORE_DECAYCHANNELS_H_ diff --git a/PWGHF/D2H/Core/SelectorCutsRedDataFormat.h b/PWGHF/D2H/Core/SelectorCutsRedDataFormat.h index 039de3834df..4373ded905c 100644 --- a/PWGHF/D2H/Core/SelectorCutsRedDataFormat.h +++ b/PWGHF/D2H/Core/SelectorCutsRedDataFormat.h @@ -29,7 +29,7 @@ namespace hf_cuts_d_daughter static constexpr int NBinsPt = 7; static constexpr int NCutVars = 6; constexpr double BinsPt[NBinsPt + 1] = { - 1., + 0., 2., 4., 6., @@ -87,5 +87,15 @@ static const std::vector labelsPt{}; // column labels static const std::vector labelsCutVar = {"invMassLow", "invMassHigh", "cpaMin", "dcaMax", "radiusMin"}; } // namespace hf_cuts_v0_daughter + +namespace hf_cuts_track_daughter +{ +static constexpr int NCutVars = 7; +// default values for the cuts +constexpr double Cuts[1][NCutVars] = {{0.1, 3, 40, 4, 3, -1, -1}}; // nSigmaTpc, nSigmaTof, nSigmaCombined +// row labels +static const std::vector labelsCutVar = {"ptMin", "itsNClsMin", "tpcNCrossedRowsMin", "tpcChi2Max", "nSigmaTpc", "nSigmaTof", "nSigmaComb"}; +} // namespace hf_cuts_track_daughter + } // namespace o2::analysis #endif // PWGHF_D2H_CORE_SELECTORCUTSREDDATAFORMAT_H_ diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index e030186b6bc..e5a776c02c4 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -215,6 +215,8 @@ DECLARE_SOA_DYNAMIC_COLUMN(EtaProng1, etaProng1, //! [](float pxProng1, float pyProng1, float pzProng1) -> float { return RecoDecay::eta(std::array{pxProng1, pyProng1, pzProng1}); }); DECLARE_SOA_DYNAMIC_COLUMN(EtaProng2, etaProng2, //! [](float pxProng2, float pyProng2, float pzProng2) -> float { return RecoDecay::eta(std::array{pxProng2, pyProng2, pzProng2}); }); +DECLARE_SOA_DYNAMIC_COLUMN(PVector, pVector, //! 3-momentum vector + [](float px, float py, float pz) -> std::array { return {px, py, pz}; }); } // namespace hf_track_vars_reduced namespace hf_b_to_jpsi_track_vars_reduced @@ -1159,8 +1161,10 @@ DECLARE_SOA_TABLE(HfCandLbConfigs, "AOD", "HFCANDLBCONFIG", //! Table with confi // Charm resonances analysis namespace hf_reso_3_prong { -DECLARE_SOA_COLUMN(DType, dType, int8_t); //! Integer with selected D candidate type: 1 = Dplus, -1 = Dminus, 2 = DstarPlus, -2 = DstarMinus - +DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! Integer with selected D candidate sign +DECLARE_SOA_COLUMN(ItsNClsSoftPi, itsNClsSoftPi, int); //! minimum value of number of ITS clusters for the decay daughter tracks +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsSoftPi, tpcNClsCrossedRowsSoftPi, int); //! minimum value of number of TPC crossed rows for the decay daughter tracks +DECLARE_SOA_COLUMN(TpcChi2NClSoftPi, tpcChi2NClSoftPi, float); //! maximum value of TPC chi2 for the decay daughter tracks DECLARE_SOA_DYNAMIC_COLUMN(Px, px, //! [](float pxProng0, float pxProng1, float pxProng2) -> float { return 1.f * pxProng0 + 1.f * pxProng1 + 1.f * pxProng2; }); DECLARE_SOA_DYNAMIC_COLUMN(Py, py, //! @@ -1272,7 +1276,8 @@ DECLARE_SOA_TABLE(HfRedTrkNoParams, "AOD", "HFREDTRKNOPARAM", //! Table with tra hf_track_vars_reduced::Phi, hf_track_pid_reduced::TPCTOFNSigmaPi, hf_track_pid_reduced::TPCTOFNSigmaKa, - hf_track_pid_reduced::TPCTOFNSigmaPr); + hf_track_pid_reduced::TPCTOFNSigmaPr, + hf_track_vars_reduced::PVector); DECLARE_SOA_TABLE(HfRed3PrNoTrks, "AOD", "HFRED3PRNOTRK", //! Table with 3 prong candidate information for resonances reduced workflow o2::soa::Index<>, @@ -1285,7 +1290,7 @@ DECLARE_SOA_TABLE(HfRed3PrNoTrks, "AOD", "HFRED3PRNOTRK", //! Table with 3 prong hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2, hf_track_vars_reduced::ItsNClsProngMin, hf_track_vars_reduced::TpcNClsCrossedRowsProngMin, hf_track_vars_reduced::TpcChi2NClProngMax, - hf_reso_3_prong::DType, + hf_reso_3_prong::Sign, // Dynamic hf_reso_3_prong::Px, hf_reso_3_prong::Py, @@ -1297,10 +1302,6 @@ DECLARE_SOA_TABLE(HfRed3PrNoTrks, "AOD", "HFRED3PRNOTRK", //! Table with 3 prong hf_track_vars_reduced::EtaProng1, hf_track_vars_reduced::EtaProng2, hf_reso_3_prong::InvMassDplus, - hf_cand_dstar::InvMassDstar, - hf_cand_dstar::InvMassAntiDstar, - hf_cand_dstar::InvMassD0, - hf_cand_dstar::InvMassD0Bar, hf_reso_3_prong::Pt, hf_cand::PVectorProng0, hf_cand::PVectorProng1, @@ -1334,24 +1335,55 @@ DECLARE_SOA_TABLE(HfRed2PrNoTrks, "AOD", "HFRED2PRNOTRK", //! Table with 2 prong hf_cand_dstar::InvMassD0, hf_cand_dstar::InvMassD0Bar); +DECLARE_SOA_TABLE(HfRedDstarNoTrks, "AOD", "HFREDDSTARNOTRK", //! Table with 3 prong candidate information for resonances reduced workflow + o2::soa::Index<>, + // Indices + hf_track_index_reduced::Prong0Id, hf_track_index_reduced::Prong1Id, hf_track_index_reduced::Prong2Id, + hf_track_index_reduced::HfRedCollisionId, + // Static + hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, + hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, + hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, + hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2, + hf_track_vars_reduced::ItsNClsProngMin, hf_track_vars_reduced::TpcNClsCrossedRowsProngMin, hf_track_vars_reduced::TpcChi2NClProngMax, + hf_reso_3_prong::ItsNClsSoftPi, hf_reso_3_prong::TpcNClsCrossedRowsSoftPi, hf_reso_3_prong::TpcChi2NClSoftPi, + hf_reso_3_prong::Sign, + // Dynamic + hf_reso_3_prong::Px, + hf_reso_3_prong::Py, + hf_reso_3_prong::Pz, + hf_track_vars_reduced::PtProng0, + hf_track_vars_reduced::PtProng1, + hf_track_vars_reduced::PtProng2, + hf_track_vars_reduced::EtaProng0, + hf_track_vars_reduced::EtaProng1, + hf_track_vars_reduced::EtaProng2, + hf_cand_dstar::InvMassDstar, + hf_cand_dstar::InvMassAntiDstar, + hf_cand_dstar::InvMassD0, + hf_cand_dstar::InvMassD0Bar, + hf_reso_3_prong::Pt, + hf_cand::PVectorProng0, + hf_cand::PVectorProng1, + hf_cand::PVectorProng2, + hf_reso_3_prong::PVector); + namespace hf_reso_cand_reduced { DECLARE_SOA_COLUMN(InvMass, invMass, float); //! Invariant mass in GeV/c2 DECLARE_SOA_COLUMN(InvMassProng0, invMassProng0, float); //! Invariant Mass of D daughter in GeV/c -DECLARE_SOA_COLUMN(InvMassProng1, invMassProng1, float); //! Invariant Mass of V0 daughter in GeV/c -DECLARE_SOA_COLUMN(InvMassD0, invMassD0, float); //! Invariant Mass of potential D0 daughter +DECLARE_SOA_COLUMN(InvMassProng1, invMassProng1, float); //! Invariant Mass of V0/Tr daughter in GeV/c +DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! Sign of the Resonance candidate +DECLARE_SOA_COLUMN(IsWrongSign, isWrongSign, int8_t); //! Flag for wrong sign of the Resonance candidate, 1 = wrong sign, 0 = right sign -DECLARE_SOA_COLUMN(MlScoreBkgProng0, mlScoreBkgProng0, float); //! Bkg ML score of the D daughter -DECLARE_SOA_COLUMN(MlScorePromptProng0, mlScorePromptProng0, float); //! Prompt ML score of the D daughter -DECLARE_SOA_COLUMN(MlScoreNonpromptProng0, mlScoreNonpromptProng0, float); //! Nonprompt ML score of the D daughter - -DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed3PrNoTrks, "_0"); //! Prong0 index (D daughter) -DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedVzeros, "_1"); //! Prong1 index (V0 daughter) -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // flag for decay channel classification reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // flag for resonance decay channel classification reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchRecD, flagMcMatchRecD, int8_t); // flag for D meson bachelor decay channel classification reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchChanD, flagMcMatchChanD, int8_t); // flag for D meson resonant channel classification reconstruction level DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // flag for decay channel classification generator level -DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association at reconstruction level +DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, uint16_t); // debug flag for mis-association at reconstruction level DECLARE_SOA_COLUMN(Origin, origin, int8_t); // Flag for origin of MC particle 1=promt, 2=FD DECLARE_SOA_COLUMN(SignD0, signD0, int8_t); // Sign of the D0 in the channels with D* -> D0 pi, needed in case of non-matched D* +DECLARE_SOA_COLUMN(PtGen, ptGen, float); // Pt at generation level in GeV/c DECLARE_SOA_COLUMN(InvMassGen, invMassGen, float); //! Invariant mass at generation level in GeV/c2 DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! [](float pxProng0, float pxProng1, float pyProng0, float pyProng1) -> float { return RecoDecay::pt((1.f * pxProng0 + 1.f * pxProng1), (1.f * pyProng0 + 1.f * pyProng1)); }); @@ -1359,14 +1391,39 @@ DECLARE_SOA_DYNAMIC_COLUMN(PtProng0, ptProng0, //! [](float pxProng0, float pyProng0) -> float { return RecoDecay::pt(pxProng0, pyProng0); }); DECLARE_SOA_DYNAMIC_COLUMN(PtProng1, ptProng1, //! [](float pxProng1, float pyProng1) -> float { return RecoDecay::pt(pxProng1, pyProng1); }); -DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStarDs1, cosThetaStarDs1, //! costhetastar under Ds1 hypothesis - [](float px0, float py0, float pz0, float px1, float py1, float pz1, float invMass) -> float { return RecoDecay::cosThetaStar(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, std::array{o2::constants::physics::MassDStar, o2::constants::physics::MassK0}, invMass, 1); }); -DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStarDs2Star, cosThetaStarDs2Star, //! costhetastar under Ds2Star hypothesis - [](float px0, float py0, float pz0, float px1, float py1, float pz1, float invMass) -> float { return RecoDecay::cosThetaStar(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, std::array{o2::constants::physics::MassDPlus, o2::constants::physics::MassK0}, invMass, 1); }); -DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStarXiC3055, cosThetaStarXiC3055, //! costhetastar under XiC3055 hypothesis - [](float px0, float py0, float pz0, float px1, float py1, float pz1, float invMass) -> float { return RecoDecay::cosThetaStar(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, std::array{o2::constants::physics::MassDPlus, o2::constants::physics::MassLambda0}, invMass, 1); }); } // namespace hf_reso_cand_reduced +namespace hf_reso_3pr_v0 +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed3PrNoTrks, "_0"); //! Prong0 index (D daughter) +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedVzeros, "_1"); //! Prong1 index (V0 daughter) +} // namespace hf_reso_3pr_v0 +namespace hf_reso_dstar_v0 +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRedDstarNoTrks, "_0"); //! Prong0 index (D daughter) +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedVzeros, "_1"); //! Prong1 index (V0 daughter) +} // namespace hf_reso_dstar_v0 +namespace hf_reso_2pr_v0 +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed2PrNoTrks, "_0"); //! Prong0 index (D daughter) +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedVzeros, "_1"); //! Prong1 index (V0 daughter) +} // namespace hf_reso_2pr_v0 +namespace hf_reso_3pr_trk +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed3PrNoTrks, "_0"); //! Prong0 index (D daughter) +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrkNoParams, "_1"); //! Prong1 index (Track daughter) +} // namespace hf_reso_3pr_trk +namespace hf_reso_dstar_trk +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRedDstarNoTrks, "_0"); //! Prong0 index (D daughter) +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrkNoParams, "_1"); //! Prong1 index (Track daughter) +} // namespace hf_reso_dstar_trk +namespace hf_reso_2pr_trk +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed2PrNoTrks, "_0"); //! Prong0 index (D daughter) +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrkNoParams, "_1"); //! Prong1 index (Track daughter) +} // namespace hf_reso_2pr_trk + DECLARE_SOA_TABLE(HfCandCharmReso, "AOD", "HFCANDCHARMRESO", //! Table with Resonance candidate information for resonances reduced workflow o2::soa::Index<>, // Static @@ -1375,10 +1432,8 @@ DECLARE_SOA_TABLE(HfCandCharmReso, "AOD", "HFCANDCHARMRESO", //! Table with Reso hf_reso_cand_reduced::InvMass, hf_reso_cand_reduced::InvMassProng0, hf_reso_cand_reduced::InvMassProng1, - hf_reso_v0::Cpa, - hf_reso_v0::Dca, - hf_reso_v0::Radius, - hf_reso_cand_reduced::InvMassD0, + hf_reso_cand_reduced::Sign, + hf_reso_cand_reduced::IsWrongSign, // Dynamic hf_reso_cand_reduced::Pt, hf_reso_cand_reduced::PtProng0, @@ -1387,33 +1442,111 @@ DECLARE_SOA_TABLE(HfCandCharmReso, "AOD", "HFCANDCHARMRESO", //! Table with Reso hf_reso_v0::Py, hf_reso_v0::Pz, hf_cand::PVectorProng0, - hf_cand::PVectorProng1, - hf_reso_cand_reduced::CosThetaStarDs1, - hf_reso_cand_reduced::CosThetaStarDs2Star, - hf_reso_cand_reduced::CosThetaStarXiC3055); + hf_cand::PVectorProng1); -DECLARE_SOA_TABLE(HfResoIndices, "AOD", "HFRESOINDICES", //! Table with Indices of resonance daughters for MC matching +DECLARE_SOA_TABLE(Hf3PrV0Ids, "AOD", "HF3PRV0ID", hf_track_index_reduced::HfRedCollisionId, - hf_reso_cand_reduced::Prong0Id, - hf_reso_cand_reduced::Prong1Id); - -DECLARE_SOA_TABLE(HfCharmResoMLs, "AOD", "HFCHARMRESOML", //! Table with ML scores for the D daughter - hf_reso_cand_reduced::MlScoreBkgProng0, - hf_reso_cand_reduced::MlScorePromptProng0, - hf_reso_cand_reduced::MlScoreNonpromptProng0, - o2::soa::Marker<1>); + hf_reso_3pr_v0::Prong0Id, + hf_reso_3pr_v0::Prong1Id); +DECLARE_SOA_TABLE(HfDstarV0Ids, "AOD", "HFDSTARV0ID", + hf_track_index_reduced::HfRedCollisionId, + hf_reso_dstar_v0::Prong0Id, + hf_reso_dstar_v0::Prong1Id); +DECLARE_SOA_TABLE(Hf2PrV0Ids, "AOD", "HF2PRV0ID", + hf_track_index_reduced::HfRedCollisionId, + hf_reso_2pr_v0::Prong0Id, + hf_reso_2pr_v0::Prong1Id); +DECLARE_SOA_TABLE(Hf3PrTrkIds, "AOD", "HF3PRTRKID", + hf_track_index_reduced::HfRedCollisionId, + hf_reso_3pr_trk::Prong0Id, + hf_reso_3pr_trk::Prong1Id); +DECLARE_SOA_TABLE(HfDstarTrkIds, "AOD", "HFDSTARTRKID", + hf_track_index_reduced::HfRedCollisionId, + hf_reso_dstar_trk::Prong0Id, + hf_reso_dstar_trk::Prong1Id); +DECLARE_SOA_TABLE(Hf2PrTrkIds, "AOD", "HF2PRTRKID", + hf_track_index_reduced::HfRedCollisionId, + hf_reso_2pr_trk::Prong0Id, + hf_reso_2pr_trk::Prong1Id); // Tables for MC Resonance analysis // table with results of reconstruction level MC matching -DECLARE_SOA_TABLE(HfMcRecRedDV0s, "AOD", "HFMCRECREDDV0", //! Table with reconstructed MC information on DV0(<-Ds*) pairs for reduced workflow - hf_reso_cand_reduced::Prong0Id, - hf_reso_cand_reduced::Prong1Id, +DECLARE_SOA_TABLE(Hf3PrV0McRec, "AOD", "HF3PRV0MCREC", + hf_reso_3pr_v0::Prong0Id, + hf_reso_3pr_v0::Prong1Id, + hf_reso_cand_reduced::FlagMcMatchRec, + hf_reso_cand_reduced::FlagMcMatchRecD, + hf_reso_cand_reduced::FlagMcMatchChanD, + hf_reso_cand_reduced::DebugMcRec, + hf_reso_cand_reduced::Origin, + hf_reso_cand_reduced::PtGen, + hf_reso_cand_reduced::InvMassGen, + hf_cand::NTracksDecayed, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(HfDstarV0McRec, "AOD", "HFDSTARV0MCREC", + hf_reso_dstar_v0::Prong0Id, + hf_reso_dstar_v0::Prong1Id, + hf_reso_cand_reduced::FlagMcMatchRec, + hf_reso_cand_reduced::FlagMcMatchRecD, + hf_reso_cand_reduced::FlagMcMatchChanD, + hf_reso_cand_reduced::DebugMcRec, + hf_reso_cand_reduced::Origin, + hf_reso_cand_reduced::PtGen, + hf_reso_cand_reduced::InvMassGen, + hf_cand::NTracksDecayed, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(Hf2PrV0McRec, "AOD", "HF2PRV0MCREC", + hf_reso_2pr_v0::Prong0Id, + hf_reso_2pr_v0::Prong1Id, + hf_reso_cand_reduced::FlagMcMatchRec, + hf_reso_cand_reduced::FlagMcMatchRecD, + hf_reso_cand_reduced::FlagMcMatchChanD, + hf_reso_cand_reduced::DebugMcRec, + hf_reso_cand_reduced::Origin, + hf_reso_cand_reduced::PtGen, + hf_reso_cand_reduced::InvMassGen, + hf_cand::NTracksDecayed, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(Hf3PrTrkMcRec, "AOD", "HF3PRTRKMCREC", + hf_reso_3pr_trk::Prong0Id, + hf_reso_3pr_trk::Prong1Id, + hf_reso_cand_reduced::FlagMcMatchRec, + hf_reso_cand_reduced::FlagMcMatchRecD, + hf_reso_cand_reduced::FlagMcMatchChanD, + hf_reso_cand_reduced::DebugMcRec, + hf_reso_cand_reduced::Origin, + hf_reso_cand_reduced::PtGen, + hf_reso_cand_reduced::InvMassGen, + hf_cand::NTracksDecayed, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(HfDstarTrkMcRec, "AOD", "HFDSTARTRKMCREC", + hf_reso_dstar_trk::Prong0Id, + hf_reso_dstar_trk::Prong1Id, + hf_reso_cand_reduced::FlagMcMatchRec, + hf_reso_cand_reduced::FlagMcMatchRecD, + hf_reso_cand_reduced::FlagMcMatchChanD, + hf_reso_cand_reduced::DebugMcRec, + hf_reso_cand_reduced::Origin, + hf_reso_cand_reduced::PtGen, + hf_reso_cand_reduced::InvMassGen, + hf_cand::NTracksDecayed, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(Hf2PrTrkMcRec, "AOD", "HF2PRTRKMCREC", + hf_reso_2pr_trk::Prong0Id, + hf_reso_2pr_trk::Prong1Id, hf_reso_cand_reduced::FlagMcMatchRec, + hf_reso_cand_reduced::FlagMcMatchRecD, + hf_reso_cand_reduced::FlagMcMatchChanD, hf_reso_cand_reduced::DebugMcRec, hf_reso_cand_reduced::Origin, - hf_reso_cand_reduced::SignD0, - hf_b0_mc::PtMother, + hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, + hf_cand::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(HfMcGenRedResos, "AOD", "HFMCGENREDRESO", //! Generation-level MC information on Ds-Resonances candidates for reduced workflow @@ -1428,23 +1561,19 @@ DECLARE_SOA_TABLE(HfMcGenRedResos, "AOD", "HFMCGENREDRESO", //! Generation-level hf_b0_mc::PtProng1, hf_b0_mc::YProng1, hf_b0_mc::EtaProng1, + hf_reso_cand_reduced::InvMassGen, + hf_reduced_collision::HfCollisionRejectionMap, o2::soa::Marker<1>); -DECLARE_SOA_TABLE(HfCandChaResTr, "AOD", "HFCANDCHARESTR", //! Table with Resonance candidate information for resonances plus tracks reduced workflow - // Static - hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, - hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, - hf_reso_cand_reduced::InvMass, - hf_reso_cand_reduced::InvMassProng0, - // Dynamic - hf_reso_cand_reduced::PtProng0); - // Table with same size as HfCandCharmReso DECLARE_SOA_TABLE(HfMcRecRedResos, "AOD", "HFMCRECREDRESO", //! Reconstruction-level MC information on Ds-Resonances candidates for reduced workflow hf_reso_cand_reduced::FlagMcMatchRec, + hf_reso_cand_reduced::FlagMcMatchRecD, + hf_reso_cand_reduced::FlagMcMatchChanD, hf_reso_cand_reduced::DebugMcRec, hf_reso_cand_reduced::Origin, - hf_b0_mc::PtMother, + hf_reso_cand_reduced::PtGen, + hf_reso_cand_reduced::InvMassGen, o2::soa::Marker<1>); } // namespace aod diff --git a/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx index 705a4957bbf..55ba9628f9a 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx @@ -18,6 +18,7 @@ #include "PWGHF/D2H/Core/SelectorCutsRedDataFormat.h" #include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "PWGHF/Utils/utilsMcMatching.h" #include "Common/Core/RecoDecay.h" @@ -57,17 +58,13 @@ using namespace o2::constants::physics; enum Selections : uint8_t { NoSel = 0, DSel, - V0Sel, - TrackSel, + BachSel, NSelSteps }; -enum DecayChannel : uint8_t { - Ds1ToDstarK0s = 0, - Ds2StarToDplusK0s, - XcToDplusLambda, - LambdaDminus, - DstarTrack, - D0Track + +enum D0Sel : uint8_t { + selectedD0 = 0, + selectedD0Bar }; enum DType : uint8_t { @@ -76,654 +73,821 @@ enum DType : uint8_t { D0 }; +enum BachelorType : uint8_t { + V0 = 1, + Track +}; + enum V0Type : uint8_t { K0s = 0, Lambda, AntiLambda }; -enum D0SelectionType : uint8_t { - SelectedD0 = 0, - SelectedD0Bar -}; - -enum DecayTypeMc : uint8_t { - Ds1ToDStarK0ToD0PiK0s = 1, - Ds2StarToDplusK0sToPiKaPiPiPi, - Ds1ToDStarK0ToDPlusPi0K0s, - Ds1ToDStarK0ToD0PiK0sPart, - Ds1ToDStarK0ToD0NoPiK0sPart, - Ds1ToDStarK0ToD0PiK0sOneMu, - Ds2StarToDplusK0sOneMu +enum TrackType : uint8_t { + Pion = 0, + Kaon, + Proton }; -const int nBinsPt = 7; -constexpr double BinsPt[nBinsPt + 1] = { - 1., - 2., - 4., - 6., - 8., - 12., - 24., - 1000.}; -auto vecBinsPt = std::vector{BinsPt, BinsPt + nBinsPt + 1}; - struct HfCandidateCreatorCharmResoReduced { // Produces: Tables with resonance info Produces rowCandidateReso; - Produces rowCandidateResoTrack; - // Optional daughter ML scores table - Produces mlScores; - // Table with candidate indices for MC matching - Produces rowCandidateResoIndices; - - // Configurables - Configurable rejectDV0PairsWithCommonDaughter{"rejectDV0PairsWithCommonDaughter", true, "flag to reject the pairs that share a daughter track if not done in the derived data creation"}; - Configurable keepSideBands{"keepSideBands", false, "flag to keep events from D meson sidebands for backgorund estimation"}; - // QA switch - Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; - Configurable> binsPt{"binsPt", std::vector{vecBinsPt}, "Histogram pT bin limits"}; - // Daughters selection cuts - Configurable> cutsDDaughter{"cutsDDaughter", {hf_cuts_d_daughter::Cuts[0], hf_cuts_d_daughter::NBinsPt, hf_cuts_d_daughter::NCutVars, hf_cuts_d_daughter::labelsPt, hf_cuts_d_daughter::labelsCutVar}, "D daughter selections"}; - Configurable> binsPtD{"binsPtD", std::vector{hf_cuts_d_daughter::vecBinsPt}, "pT bin limits for D daughter cuts"}; - Configurable> cutsV0Daughter{"cutsV0Daughter", {hf_cuts_v0_daughter::Cuts[0], hf_cuts_v0_daughter::NBinsPt, hf_cuts_v0_daughter::NCutVars, hf_cuts_v0_daughter::labelsPt, hf_cuts_v0_daughter::labelsCutVar}, "V0 daughter selections"}; - Configurable> binsPtV0{"binsPtV0", std::vector{hf_cuts_v0_daughter::vecBinsPt}, "pT bin limits for V0 daughter cuts"}; - - // Configurables for ME - Configurable numberEventsMixed{"numberEventsMixed", 5, "Number of events mixed in ME process"}; - Configurable numberEventsToSkip{"numberEventsToSkip", -1, "Number of events to Skip in ME process"}; + // Tables with bachelors indices for MC matching and Task + Produces rowCandidateResoIndices3PrV0s; + Produces rowCandidateResoIndicesDstarV0s; + Produces rowCandidateResoIndices2PrV0s; + Produces rowCandidateResoIndices3PrTrks; + Produces rowCandidateResoIndicesDstarTrks; + Produces rowCandidateResoIndices2PrTrks; + // D Configurables + struct : ConfigurableGroup { + Configurable> binsPtD{"binsPtD", std::vector{hf_cuts_d_daughter::vecBinsPt}, "pT bin limits for D daughter cuts"}; + Configurable> cutsD{"cutsD", {hf_cuts_d_daughter::Cuts[0], hf_cuts_d_daughter::NBinsPt, hf_cuts_d_daughter::NCutVars, hf_cuts_d_daughter::labelsPt, hf_cuts_d_daughter::labelsCutVar}, "D daughter selections"}; + Configurable keepSideBands{"keepSideBands", false, "flag to keep events from D meson sidebands for backgorund estimation"}; + } cfgDmesCuts; + // V0 cuts configurables + struct : ConfigurableGroup { + Configurable> cutsV0{"cutsV0", {hf_cuts_v0_daughter::Cuts[0], hf_cuts_v0_daughter::NBinsPt, hf_cuts_v0_daughter::NCutVars, hf_cuts_v0_daughter::labelsPt, hf_cuts_v0_daughter::labelsCutVar}, "V0 daughter selections"}; + Configurable> binsPtV0{"binsPtV0", std::vector{hf_cuts_v0_daughter::vecBinsPt}, "pT bin limits for V0 daughter cuts"}; + Configurable v0Type{"v0Type", 0, "V0 type to be selected (0: K0s, 1: Lambda"}; + } cfgV0Cuts; + // Track cuts configurables + struct : ConfigurableGroup { + Configurable> cutsTrk{"cutsTrk", {hf_cuts_track_daughter::Cuts[0], hf_cuts_track_daughter::NCutVars, hf_cuts_track_daughter::labelsCutVar}, "Track daughter selections, set to -1 to disable cuts"}; + Configurable massHypo{"massHypo", 1, "Mass Hypothesis for the track daughters (0: pion, 1: kaon, 2: proton)"}; + } cfgTrackCuts; + // Mixed Event configurables + struct : ConfigurableGroup { + Configurable numberEventsMixed{"numberEventsMixed", 5, "Number of events mixed in ME process"}; + Configurable numberEventsToSkip{"numberEventsToSkip", -1, "Number of events to Skip in ME process"}; + ConfigurableAxis multPoolBins{"multPoolBins", {VARIABLE_WIDTH, 0., 45., 60., 75., 95, 250}, "event multiplicity pools (PV contributors for now)"}; + ConfigurableAxis zPoolBins{"zPoolBins", {VARIABLE_WIDTH, -10.0, -4, -1, 1, 4, 10.0}, "z vertex position pools"}; + } cfgMixedEvent; + // Histogram axes configurables + struct : ConfigurableGroup { + ConfigurableAxis axisPtD{"axisPtD", {100, 0., 50}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisPtV0{"axisPtV0", {100, 0., 50}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisPtReso{"axisPtReso", {100, 0., 50}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisMassD{"axisMassD", {100, 1.7f, 2.1f}, "inv. mass (D) (GeV/#it{c}^{2})"}; + ConfigurableAxis axisMassV0{"axisMassV0", {100, 0.45f, 0.55f}, "inv. mass (V_{0}) (GeV/#it{c}^{2})"}; + ConfigurableAxis axisMassDsj{"axisMassDsj", {400, 0.49f, 0.89f}, "inv. mass (DV_{0}) (GeV/#it{c}^{2})"}; + } cfgHistAxes; + // Other Configurables + Configurable rejectPairsWithCommonDaughter{"rejectPairsWithCommonDaughter", true, "flag to reject the pairs that share a daughter track if not done in the derived data creation"}; + Configurable useDeltaMass{"useDeltaMass", true, "Use Delta Mass for resonance invariant Mass calculation"}; SliceCache cache; - - using HfRed3PrNoTrksWithMl = soa::Join; - using HfRed2PrNoTrksWithMl = soa::Join; - Preslice candsV0PerCollision = aod::hf_track_index_reduced::hfRedCollisionId; Preslice candsTrackPerCollision = aod::hf_track_index_reduced::hfRedCollisionId; - Preslice candsDPerCollision = hf_track_index_reduced::hfRedCollisionId; - Preslice candsD0PerCollision = hf_track_index_reduced::hfRedCollisionId; - Preslice candsDPerCollisionWithMl = hf_track_index_reduced::hfRedCollisionId; - Preslice candsD0PerCollisionWithMl = hf_track_index_reduced::hfRedCollisionId; - - // Partition of V0 candidates based on v0Type - Partition candidatesK0s = aod::hf_reso_v0::v0Type == (uint8_t)1 || aod::hf_reso_v0::v0Type == (uint8_t)3 || aod::hf_reso_v0::v0Type == (uint8_t)5; - Partition candidatesLambda = aod::hf_reso_v0::v0Type == (uint8_t)2 || aod::hf_reso_v0::v0Type == (uint8_t)4; - - ConfigurableAxis multPoolBins{"multPoolBins", {VARIABLE_WIDTH, 0., 45., 60., 75., 95, 250}, "event multiplicity pools (PV contributors for now)"}; - ConfigurableAxis zPoolBins{"zPoolBins", {VARIABLE_WIDTH, -10.0, -4, -1, 1, 4, 10.0}, "z vertex position pools"}; + Preslice cands3PrPerCollision = hf_track_index_reduced::hfRedCollisionId; + Preslice candsDstarPerCollision = hf_track_index_reduced::hfRedCollisionId; + Preslice cands2PrPerCollision = hf_track_index_reduced::hfRedCollisionId; HistogramRegistry registry{"registry"}; void init(InitContext const&) { - // check that only one process function is enabled - std::array doprocess{doprocessDs2StarToDplusK0s, doprocessDs2StarToDplusK0sWithMl, doprocessDs1ToDstarK0s, doprocessDs1ToDstarK0sWithMl, doprocessDs1ToDstarK0sMixedEvent, doprocessDs1ToDstarK0sMixedEventWithMl, doprocessDs2StarToDplusK0sMixedEventWithMl, - doprocessXcToDplusLambda, doprocessXcToDplusLambdaWithMl, doprocessLambdaDminus, doprocessLambdaDminusWithMl, doprocessDstarTrack, doprocessDstarTrackWithMl, doprocessD0Track, doprocessD0TrackWithMl}; - if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { - LOGP(fatal, "Only one process function should be enabled! Please check your configuration!"); - } // histograms - const AxisSpec axisPt{(std::vector)vecBinsPt, "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec axisMassDsj{400, 0.49f, 0.89f, ""}; - registry.add("hMassDs1", "Ds1 candidates;m_{Ds1} (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisMassDsj, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hMassDs2Star", "Ds^{*}2 candidates; m_Ds^{*}2 (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {axisMassDsj, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hMassXcRes", "XcRes candidates; m_XcRes (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{300, 1.1, 1.4}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hMassLambdaDminus", "LambdaDminus candidates; m_LambdaDminus (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{300, 1.1, 1.4}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hMassDstarTrack", "DstarTrack candidates; m_DstarTrack (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{100, 0.9, 1.4}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hMassD0Track", "D0Track candidates; m_D0Track (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{100, 0.8, 1.3}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hMassD0BarTrack", "D0Track candidates; m_D0Track (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{100, 0.8, 1.3}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - if (doprocessDs1ToDstarK0sMixedEvent) { - registry.add("hNPvContCorr", "Collision number of PV contributors ; N contrib ; N contrib", {HistType::kTH2F, {{100, 0, 250}, {100, 0, 250}}}); - registry.add("hZvertCorr", "Collision Z Vtx ; z PV [cm] ; z PV [cm]", {HistType::kTH2F, {{120, -12., 12.}, {120, -12., 12.}}}); + registry.add("hMassDmesDauVsPt", "D daughter candidates inv. mass", {HistType::kTH2F, {cfgHistAxes.axisMassD, cfgHistAxes.axisPtD}}); + registry.add("hMassV0DauVsPt", "V0 daughter candidates inv. mass", {HistType::kTH2F, {cfgHistAxes.axisMassV0, cfgHistAxes.axisPtV0}}); + registry.add("hMassResoVsPt", "Resonance candidates inv. mass", {HistType::kTH2F, {cfgHistAxes.axisMassDsj, cfgHistAxes.axisPtReso}}); + registry.add("hNPvContCorr", "Collision number of PV contributors ; N contrib ; N contrib", {HistType::kTH2F, {{100, 0, 250}, {100, 0, 250}}}); + registry.add("hZvertCorr", "Collision Z Vtx ; z PV [cm] ; z PV [cm]", {HistType::kTH2F, {{120, -12., 12.}, {120, -12., 12.}}}); + constexpr int kNBinsSelections = Selections::NSelSteps; + std::string labels[kNBinsSelections]; + labels[Selections::NoSel] = "No selection"; + labels[Selections::DSel] = "D Candidates Selection"; + labels[Selections::BachSel] = "D & other bach. Selection"; + static const AxisSpec axisSelections = {kNBinsSelections, 0.5, kNBinsSelections + 0.5, ""}; + registry.add("hSelections", "Selections", {HistType::kTH1F, {axisSelections}}); + for (int iBin = 0; iBin < kNBinsSelections; ++iBin) { + registry.get(HIST("hSelections"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); } + } - if (activateQA) { - constexpr int kNBinsSelections = Selections::NSelSteps; - std::string labels[kNBinsSelections]; - labels[Selections::NoSel] = "No selection"; - labels[Selections::DSel] = "D Candidates Selection"; - labels[Selections::V0Sel] = "D & V0 candidate Selection"; - labels[Selections::TrackSel] = "D & Track candidate Selection"; - static const AxisSpec axisSelections = {kNBinsSelections, 0.5, kNBinsSelections + 0.5, ""}; - registry.add("hSelections", "Selections", {HistType::kTH1F, {axisSelections}}); - for (int iBin = 0; iBin < kNBinsSelections; ++iBin) { - registry.get(HIST("hSelections"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); - } + bool isInMassInterval(float invMass, int ptBin) + { + if (!cfgDmesCuts.keepSideBands) { + return (invMass >= cfgDmesCuts.cutsD->get(ptBin, "invMassSignalLow") && invMass <= cfgDmesCuts.cutsD->get(ptBin, "invMassSignalHigh")); + } else { + return ((invMass >= cfgDmesCuts.cutsD->get(ptBin, "invMassLeftSBLow") && invMass <= cfgDmesCuts.cutsD->get(ptBin, "invMassLeftSBHigh")) || + (invMass >= cfgDmesCuts.cutsD->get(ptBin, "invMassRightSBLow") && invMass <= cfgDmesCuts.cutsD->get(ptBin, "invMassRightSBHigh")) || + (invMass >= cfgDmesCuts.cutsD->get(ptBin, "invMassSignalLow") && invMass <= cfgDmesCuts.cutsD->get(ptBin, "invMassSignalHigh"))); } } /// Basic selection of D candidates /// \param candD is the reduced D meson candidate /// \return true if selections are passed - template - bool isDSelected(DRedTable const& candD) + template + uint8_t selctionFlagBachD(DRedTable const& candD) { + uint8_t selection = {BIT(D0Sel::selectedD0) | BIT(D0Sel::selectedD0Bar)}; float invMassD{0.}; float ptD = candD.pt(); - int ptBin = findBin(binsPtD, ptD); + int ptBin = findBin(cfgDmesCuts.binsPtD, ptD); if (ptBin == -1) { - return false; + return 0; } - if constexpr (channel == DecayChannel::Ds2StarToDplusK0s || channel == DecayChannel::XcToDplusLambda || channel == DecayChannel::LambdaDminus) { + if constexpr (dType == DType::Dplus) { invMassD = candD.invMassDplus(); - } else if constexpr (channel == DecayChannel::Ds1ToDstarK0s || channel == DecayChannel::DstarTrack) { - if (candD.dType() > 0) + if (!isInMassInterval(invMassD, ptBin)) { + return 0; + } + } else if constexpr (dType == DType::Dstar) { + if (candD.sign() > 0) { invMassD = candD.invMassDstar() - candD.invMassD0(); - else + } else { invMassD = candD.invMassAntiDstar() - candD.invMassD0Bar(); - } - // invariant mass selection - if (!keepSideBands) { - if constexpr (channel == DecayChannel::D0Track) { - if ((candD.invMassD0() < cutsDDaughter->get(ptBin, "invMassSignalLow") || candD.invMassD0() > cutsDDaughter->get(ptBin, "invMassSignalHigh")) && - (candD.invMassD0Bar() < cutsDDaughter->get(ptBin, "invMassSignalLow") || candD.invMassD0Bar() > cutsDDaughter->get(ptBin, "invMassSignalHigh"))) { - return false; + } + if (!isInMassInterval(invMassD, ptBin)) { + return 0; + } + } else if constexpr (dType == DType::D0) { + if (TESTBIT(candD.selFlagD0(), D0Sel::selectedD0)) { + invMassD = candD.invMassD0(); + if (!isInMassInterval(invMassD, ptBin)) { + CLRBIT(selection, D0Sel::selectedD0); } } else { - if (invMassD < cutsDDaughter->get(ptBin, "invMassSignalLow") || invMassD > cutsDDaughter->get(ptBin, "invMassSignalHigh")) { - return false; - } + CLRBIT(selection, D0Sel::selectedD0); } - } else { - if ((invMassD < cutsDDaughter->get(ptBin, "invMassLeftSBLow")) || - (invMassD > cutsDDaughter->get(ptBin, "invMassLeftSBHigh") && invMassD < cutsDDaughter->get(ptBin, "invMassSignalLow")) || - (invMassD > cutsDDaughter->get(ptBin, "invMassSignalHigh") && invMassD < cutsDDaughter->get(ptBin, "invMassRightSBLow")) || - (invMassD > cutsDDaughter->get(ptBin, "invMassRightSBHigh"))) { - return false; + if (TESTBIT(candD.selFlagD0(), D0Sel::selectedD0Bar)) { + invMassD = candD.invMassD0Bar(); + if (!isInMassInterval(invMassD, ptBin)) { + CLRBIT(selection, D0Sel::selectedD0Bar); + } + } else { + CLRBIT(selection, D0Sel::selectedD0Bar); } } - return true; + return selection; } /// Basic selection of V0 and track candidates /// \param candV0 is the reduced V0 candidate - /// \param candD is the reduced D meson candidate /// \return true if selections are passed - template - bool isV0Selected(V0RedTable const& candV0, DRedTable const& candD) + template + bool isV0Selected(V0RedTable const& candV0) { - float massV0{0.}; - float invMassV0{0.}; - float ptV0 = candV0.pt(); - int ptBin = findBin(binsPtV0, ptV0); + int ptBin = findBin(cfgV0Cuts.binsPtV0, candV0.pt()); if (ptBin == -1) { return false; } - if (channel == DecayChannel::Ds2StarToDplusK0s || channel == DecayChannel::Ds1ToDstarK0s) { - massV0 = MassK0Short; - invMassV0 = candV0.invMassK0s(); - } else if (channel == DecayChannel::XcToDplusLambda || channel == DecayChannel::LambdaDminus) { - massV0 = MassLambda; - int wsFact{1}; - if (channel == DecayChannel::LambdaDminus) - wsFact = -1; - uint8_t targetV0Type{0}; - if (wsFact * candD.dType() > 0) { - invMassV0 = candV0.invMassLambda(); - targetV0Type = V0Type::Lambda; - } else { - invMassV0 = candV0.invMassAntiLambda(); - targetV0Type = V0Type::AntiLambda; + if (cfgV0Cuts.v0Type == V0Type::K0s) { // K0s + if (!TESTBIT(candV0.v0Type(), V0Type::K0s)) { + return false; } - // check skimming cuts - if (!TESTBIT(candV0.v0Type(), targetV0Type)) { + if ((candV0.invMassK0s() - MassK0Short) > cfgV0Cuts.cutsV0->get(ptBin, "invMassLow") && (MassK0Short - candV0.invMassK0s()) < cfgV0Cuts.cutsV0->get(ptBin, "invMassLow")) { return false; } - } - // selection on V0 candidate mass - if ((invMassV0 - massV0) > cutsV0Daughter->get(ptBin, "invMassLow") && (massV0 - invMassV0) < cutsV0Daughter->get(ptBin, "invMassLow")) { + } else if (cfgV0Cuts.v0Type == V0Type::Lambda) { // Lambda + if (!TESTBIT(candV0.v0Type(), V0Type::Lambda) && !TESTBIT(candV0.v0Type(), V0Type::AntiLambda)) { + return false; + } + if ((candV0.invMassLambda() - MassLambda) > cfgV0Cuts.cutsV0->get(ptBin, "invMassLow") && (MassLambda - candV0.invMassLambda()) < cfgV0Cuts.cutsV0->get(ptBin, "invMassLow")) { + return false; + } + if ((candV0.invMassAntiLambda() - MassLambda) > cfgV0Cuts.cutsV0->get(ptBin, "invMassLow") && (MassLambda - candV0.invMassAntiLambda()) < cfgV0Cuts.cutsV0->get(ptBin, "invMassLow")) { + return false; + } + } else { + LOG(error) << "Unsupported V0 type for selection: " << cfgV0Cuts.v0Type; return false; } // selection on kinematics and topology - if (candV0.dca() > cutsV0Daughter->get(ptBin, "dcaMax") || candV0.cpa() < cutsV0Daughter->get(ptBin, "cpaMin") || candV0.v0Radius() < cutsV0Daughter->get(ptBin, "radiusMin")) { + if (candV0.dca() > cfgV0Cuts.cutsV0->get(ptBin, "dcaMax") || candV0.cpa() < cfgV0Cuts.cutsV0->get(ptBin, "cpaMin") || candV0.v0Radius() < cfgV0Cuts.cutsV0->get(ptBin, "radiusMin")) { return false; } return true; } - template - void runCandidateCreation(Coll const& collision, - DRedTable const& candsD, - V0TrRedTable const& candsV0Tr) + // Basic selection of track candidates + /// \param candTr is the reduced track candidate + /// \return true if selections are passed + template + bool isTrackSelected(TrkRedTable const& candTr) { - // loop on D candidates - for (const auto& candD : candsD) { - // selection of D candidates - if (activateQA) { - registry.fill(HIST("hSelections"), 1); + // pT selection + if (cfgTrackCuts.cutsTrk->get("ptMin") > 0 && candTr.pt() < cfgTrackCuts.cutsTrk->get("ptMin")) { + return false; + } + // ITS quality selection + if (cfgTrackCuts.cutsTrk->get("itsNClsMin") > 0 && candTr.itsNCls() < cfgTrackCuts.cutsTrk->get("itsNClsMin")) { + return false; + } + // TPC quality selection + if (cfgTrackCuts.cutsTrk->get("tpcNCrossedRowsMin") > 0 && candTr.tpcNClsCrossedRows() < cfgTrackCuts.cutsTrk->get("tpcNCrossedRowsMin")) { + return false; + } + if (cfgTrackCuts.cutsTrk->get("tpcChi2Max") > 0 && candTr.tpcChi2NCl() > cfgTrackCuts.cutsTrk->get("tpcChi2Max")) { + return false; + } + // PID selection + if (cfgTrackCuts.massHypo == TrackType::Pion) { // Pion + if (cfgTrackCuts.cutsTrk->get("nSigmaTpc") > 0 && candTr.tpcNSigmaPi() > cfgTrackCuts.cutsTrk->get("nSigmaTpc")) { + return false; } - if (!isDSelected(candD)) { - continue; + if (cfgTrackCuts.cutsTrk->get("nSigmaTof") > 0 && candTr.tofNSigmaPi() > cfgTrackCuts.cutsTrk->get("nSigmaTof")) { + return false; } - if (activateQA) { - registry.fill(HIST("hSelections"), 1 + Selections::DSel); + if (cfgTrackCuts.cutsTrk->get("nSigmaComb") > 0 && candTr.tpcTofNSigmaPi() > cfgTrackCuts.cutsTrk->get("nSigmaComb")) { + return false; } - float invMassD{0.}; - float invMassD0{0.}; - std::array, 3> pVectorCharmProngs; - if constexpr (channel != DecayChannel::D0Track) { - if (std::abs(candD.dType()) == DType::Dplus) - invMassD = candD.invMassDplus(); - if (candD.dType() == DType::Dstar) { - invMassD = candD.invMassDstar(); - invMassD0 = candD.invMassD0(); + } else if (cfgTrackCuts.massHypo == TrackType::Kaon) { // Kaon + if (cfgTrackCuts.cutsTrk->get("nSigmaTpc") > 0 && candTr.tpcNSigmaKa() > cfgTrackCuts.cutsTrk->get("nSigmaTpc")) { + return false; + } + if (cfgTrackCuts.cutsTrk->get("nSigmaTof") > 0 && candTr.tofNSigmaKa() > cfgTrackCuts.cutsTrk->get("nSigmaTof")) { + return false; + } + if (cfgTrackCuts.cutsTrk->get("nSigmaComb") > 0 && candTr.tpcTofNSigmaKa() > cfgTrackCuts.cutsTrk->get("nSigmaComb")) { + return false; + } + } else if (cfgTrackCuts.massHypo == TrackType::Proton) { // Proton + if (cfgTrackCuts.cutsTrk->get("nSigmaTpc") > 0 && candTr.tpcNSigmaPr() > cfgTrackCuts.cutsTrk->get("nSigmaTpc")) { + return false; + } + if (cfgTrackCuts.cutsTrk->get("nSigmaTof") > 0 && candTr.tofNSigmaPr() > cfgTrackCuts.cutsTrk->get("nSigmaTof")) { + return false; + } + if (cfgTrackCuts.cutsTrk->get("nSigmaComb") > 0 && candTr.tpcTofNSigmaPr() > cfgTrackCuts.cutsTrk->get("nSigmaComb")) { + return false; + } + } else { + LOG(error) << "Unsupported mass hypothesis for track selection: " << cfgTrackCuts.massHypo; + return false; + } + return true; + } + + /// Fill the output tables with the resonance candidates + /// \param collision is the collision information + /// \param candD is the reduced D meson candidate + /// \param candV0Tr is the reduced V0 or track candidate + /// \tparam dType is the type of D meson (Dplus, Dstar, D0) + /// \tparam bachType is the type of bachelor (V0 or Track) + template + void fillOutputTables(Coll const& collision, + DRedTable const& candD, + V0TrRedTable const& candV0Tr, + int selectionFlag) + { + std::vector> pVectorCharmProngs = {candD.pVectorProng0(), candD.pVectorProng1()}; + std::array pVecD = candD.pVector(); + std::array pVecV0Tr = candV0Tr.pVector(); + float invMassReso{-1}, invMassV0Tr{-1}, invMassD{-1}; + int8_t signReso{0}, isWrongSign{0}; + double ptReso = RecoDecay::pt(RecoDecay::sumOfVec(pVecV0Tr, pVecD)); + + if constexpr (dType == DType::Dplus) { + invMassD = candD.invMassDplus(); + pVectorCharmProngs.push_back(candD.pVectorProng2()); + if constexpr (bachType == BachelorType::V0) { + if (cfgV0Cuts.v0Type == V0Type::K0s) { // K0s + invMassV0Tr = candV0Tr.invMassK0s(); + signReso = candD.sign(); + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0Short}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDPlus, MassK0Short}); + } + } else if (cfgV0Cuts.v0Type == V0Type::Lambda) { // Lambda + if (candV0Tr.v0Type() == V0Type::Lambda) { + invMassV0Tr = candV0Tr.invMassLambda(); + signReso = candD.sign(); + } else if (candV0Tr.v0Type() == V0Type::AntiLambda) { + invMassV0Tr = candV0Tr.invMassAntiLambda(); + signReso = candD.sign(); + isWrongSign = 1; + } + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassLambda}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDPlus, MassLambda}); + } } - if (candD.dType() == (-1) * DType::Dstar) { - invMassD = candD.invMassAntiDstar(); - invMassD0 = candD.invMassD0Bar(); + rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], + pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], + invMassReso, + invMassD, + invMassV0Tr, + signReso, + isWrongSign); + rowCandidateResoIndices3PrV0s(collision.globalIndex(), candD.globalIndex(), candV0Tr.globalIndex()); + registry.fill(HIST("hMassResoVsPt"), invMassReso, ptReso); + registry.fill(HIST("hMassDmesDauVsPt"), invMassD, candD.pt()); + registry.fill(HIST("hMassV0DauVsPt"), invMassV0Tr, candV0Tr.pt()); + } else if constexpr (bachType == BachelorType::Track) { + signReso = candD.sign() + candV0Tr.sign(); + isWrongSign = candD.sign() * candV0Tr.sign() > 0 ? 1 : 0; + if (cfgTrackCuts.massHypo == TrackType::Pion) { // Pion + invMassV0Tr = MassPiPlus; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassPiPlus}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDPlus, MassPiPlus}); + } + } else if (cfgTrackCuts.massHypo == TrackType::Kaon) { // Kaon + invMassV0Tr = MassKPlus; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassKPlus}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDPlus, MassKPlus}); + } + } else if (cfgTrackCuts.massHypo == TrackType::Proton) { // Proton + invMassV0Tr = MassProton; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassProton}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDPlus, MassProton}); + } } - pVectorCharmProngs = {candD.pVectorProng0(), candD.pVectorProng1(), candD.pVectorProng2()}; + rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], + pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], + invMassReso, + invMassD, + invMassV0Tr, + signReso, + isWrongSign); + rowCandidateResoIndices3PrTrks(collision.globalIndex(), candD.globalIndex(), candV0Tr.globalIndex()); + registry.fill(HIST("hMassResoVsPt"), invMassReso, ptReso); + registry.fill(HIST("hMassDmesDauVsPt"), invMassD, candD.pt()); + registry.fill(HIST("hMassV0DauVsPt"), invMassV0Tr, candV0Tr.pt()); + } + } else if constexpr (dType == DType::Dstar) { + float invMassD0; + if (candD.sign() > 0) { + invMassD = candD.invMassDstar(); + invMassD0 = candD.invMassD0(); } else { - pVectorCharmProngs = {candD.pVectorProng0(), candD.pVectorProng1(), {0.}}; + invMassD = candD.invMassAntiDstar(); + invMassD0 = candD.invMassD0Bar(); } - std::array pVecD = {candD.px(), candD.py(), candD.pz()}; - - // loop on V0 or track candidates - bool alreadyCounted{false}; - for (const auto& candV0Tr : candsV0Tr) { - if (rejectDV0PairsWithCommonDaughter) { - if constexpr (channel == DecayChannel::D0Track) { - const std::array dDaughtersIDs = {candD.prong0Id(), candD.prong1Id()}; - if (std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0Tr.globalIndex()) != dDaughtersIDs.end()) { - continue; + pVectorCharmProngs.push_back(candD.pVectorProng2()); + if constexpr (bachType == BachelorType::V0) { + signReso = candD.sign(); + if (cfgV0Cuts.v0Type == V0Type::K0s) { // K0s + invMassV0Tr = candV0Tr.invMassK0s(); + if (useDeltaMass) { + if (candD.sign() > 0) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0Short}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[1], pVectorCharmProngs[0], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0Short}) - invMassD; } } else { - const std::array dDaughtersIDs = {candD.prong0Id(), candD.prong1Id(), candD.prong2Id()}; - if constexpr (channel == DecayChannel::DstarTrack) { - if (std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0Tr.globalIndex()) != dDaughtersIDs.end()) { - continue; - } + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDStar, MassK0Short}); + } + } else if (cfgV0Cuts.v0Type == V0Type::Lambda) { // Lambda + if (candV0Tr.v0Type() == V0Type::Lambda) { + invMassV0Tr = candV0Tr.invMassLambda(); + } else if (candV0Tr.v0Type() == V0Type::AntiLambda) { + invMassV0Tr = candV0Tr.invMassAntiLambda(); + isWrongSign = 1; + } + if (useDeltaMass) { + if (candD.sign() > 0) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassLambda}) - invMassD; } else { - if (std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0Tr.prong0Id()) != dDaughtersIDs.end() || std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0Tr.prong1Id()) != dDaughtersIDs.end()) { - continue; - } + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[1], pVectorCharmProngs[0], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassLambda}) - invMassD; } + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDStar, MassLambda}); } } - if constexpr ((channel != DecayChannel::DstarTrack) && (channel != DecayChannel::D0Track)) { - if (!isV0Selected(candV0Tr, candD)) { - continue; - } - if (activateQA && !alreadyCounted) { - registry.fill(HIST("hSelections"), 1 + Selections::V0Sel); - alreadyCounted = true; + rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], + pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], + invMassReso, + invMassD - invMassD0, + invMassV0Tr, + signReso, + isWrongSign); + rowCandidateResoIndicesDstarV0s(collision.globalIndex(), candD.globalIndex(), candV0Tr.globalIndex()); + registry.fill(HIST("hMassResoVsPt"), invMassReso, ptReso); + registry.fill(HIST("hMassDmesDauVsPt"), invMassD - invMassD0, candD.pt()); + registry.fill(HIST("hMassV0DauVsPt"), invMassV0Tr, candV0Tr.pt()); + } else if constexpr (bachType == BachelorType::Track) { + signReso = candD.sign() + candV0Tr.sign(); + isWrongSign = candD.sign() * candV0Tr.sign() > 0 ? 1 : 0; + if (cfgTrackCuts.massHypo == TrackType::Pion) { // Pion + invMassV0Tr = MassPiPlus; + if (useDeltaMass) { + if (candD.sign() > 0) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassPiPlus}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[1], pVectorCharmProngs[0], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassPiPlus}) - invMassD; + } + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDStar, MassPiPlus}); } - } - - float invMassReso{0.}; - float invMassV0{0.}; - std::array pVecV0Tr = {candV0Tr.px(), candV0Tr.py(), candV0Tr.pz()}; - float ptReso = RecoDecay::pt(RecoDecay::sumOfVec(pVecV0Tr, pVecD)); - - if constexpr (channel == DecayChannel::DstarTrack) { - if (candD.dType() > 0) { - invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassProton}); + } else if (cfgTrackCuts.massHypo == TrackType::Kaon) { // Kaon + invMassV0Tr = MassKPlus; + if (useDeltaMass) { + if (candD.sign() > 0) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassKPlus}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[1], pVectorCharmProngs[0], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassKPlus}) - invMassD; + } } else { - invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[1], pVectorCharmProngs[0], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassProton}); + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDStar, MassKPlus}); } - registry.fill(HIST("hMassDstarTrack"), invMassReso - invMassD, ptReso); - } else if constexpr (channel == DecayChannel::D0Track) { - if (TESTBIT(candD.selFlagD0(), D0SelectionType::SelectedD0)) { - invMassD = candD.invMassD0(); - invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassProton}); - registry.fill(HIST("hMassD0Track"), invMassReso - invMassD, ptReso); + } else if (cfgTrackCuts.massHypo == TrackType::Proton) { // Proton + invMassV0Tr = MassProton; + if (useDeltaMass) { + if (candD.sign() > 0) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassProton}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[1], pVectorCharmProngs[0], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassProton}) - invMassD; + } + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDStar, MassProton}); } - if (TESTBIT(candD.selFlagD0(), D0SelectionType::SelectedD0Bar)) { - invMassD = candD.invMassD0Bar(); - invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[1], pVectorCharmProngs[0], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassProton}); - registry.fill(HIST("hMassD0BarTrack"), invMassReso - invMassD, ptReso); + } + rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], + pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], + invMassReso, + invMassD - invMassD0, + invMassV0Tr, + signReso, + isWrongSign); + rowCandidateResoIndicesDstarTrks(collision.globalIndex(), candD.globalIndex(), candV0Tr.globalIndex()); + registry.fill(HIST("hMassResoVsPt"), invMassReso, ptReso); + registry.fill(HIST("hMassDmesDauVsPt"), invMassD, candD.pt()); + registry.fill(HIST("hMassV0DauVsPt"), invMassV0Tr, candV0Tr.pt()); + } + } else if constexpr (dType == DType::D0) { + // D0 + if (TESTBIT(selectionFlag, D0Sel::selectedD0)) { + invMassD = candD.invMassD0(); + if constexpr (bachType == BachelorType::V0) { + signReso = 0; + if (cfgV0Cuts.v0Type == V0Type::K0s) { // K0s + invMassV0Tr = candV0Tr.invMassK0s(); + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassK0Short}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0, MassK0Short}); + } + } else if (cfgV0Cuts.v0Type == V0Type::Lambda) { // Lambda + if (candV0Tr.v0Type() == V0Type::Lambda) { + invMassV0Tr = candV0Tr.invMassLambda(); + } else if (candV0Tr.v0Type() == V0Type::AntiLambda) { + invMassV0Tr = candV0Tr.invMassAntiLambda(); + isWrongSign = 1; + } + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassLambda}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0, MassLambda}); + } } - } else { - switch (channel) { - case DecayChannel::Ds1ToDstarK0s: - invMassV0 = candV0Tr.invMassK0s(); - if (candD.dType() > 0) { - invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0Short}) - invMassD; - } else { - invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[1], pVectorCharmProngs[0], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0Short}) - invMassD; - } - registry.fill(HIST("hMassDs1"), invMassReso, ptReso); - break; - case DecayChannel::Ds2StarToDplusK0s: - invMassV0 = candV0Tr.invMassK0s(); - invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0Short}) - invMassD; - registry.fill(HIST("hMassDs2Star"), invMassReso, ptReso); - break; - case DecayChannel::XcToDplusLambda: - if (candD.dType() > 0) { - invMassV0 = candV0Tr.invMassLambda(); - } else { - invMassV0 = candV0Tr.invMassAntiLambda(); - } - invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassLambda}) - invMassD; - registry.fill(HIST("hMassXcRes"), invMassReso, ptReso); - break; - case DecayChannel::LambdaDminus: - if (candD.dType() < 0) { - invMassV0 = candV0Tr.invMassLambda(); - } else { - invMassV0 = candV0Tr.invMassAntiLambda(); - } - invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassLambda}) - invMassD; - registry.fill(HIST("hMassLambdaDminus"), invMassReso, ptReso); - break; - default: - break; + rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], + pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], + invMassReso, + invMassD, + invMassV0Tr, + signReso, + isWrongSign); + rowCandidateResoIndices2PrV0s(collision.globalIndex(), candD.globalIndex(), candV0Tr.globalIndex()); + registry.fill(HIST("hMassResoVsPt"), invMassReso, ptReso); + registry.fill(HIST("hMassDmesDauVsPt"), invMassD, candD.pt()); + registry.fill(HIST("hMassV0DauVsPt"), invMassV0Tr, candV0Tr.pt()); + } else if constexpr (bachType == BachelorType::Track) { + signReso = candV0Tr.sign(); + isWrongSign = candV0Tr.sign() > 0 ? 0 : 1; + if (cfgTrackCuts.massHypo == TrackType::Pion) { // Pion + invMassV0Tr = MassPiPlus; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0, MassPiPlus}); + } + } else if (cfgTrackCuts.massHypo == TrackType::Kaon) { // Kaon + invMassV0Tr = MassKPlus; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassKPlus}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0, MassKPlus}); + } + } else if (cfgTrackCuts.massHypo == TrackType::Proton) { // Proton + invMassV0Tr = MassProton; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassProton}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0, MassProton}); + } } - } - // Filling Output table - if constexpr (channel == DecayChannel::DstarTrack) { - rowCandidateResoTrack(pVecD[0], pVecD[1], pVecD[2], - candV0Tr.px(), candV0Tr.py(), candV0Tr.pz(), - invMassReso, - invMassD - invMassD0); - } else if constexpr (channel == DecayChannel::D0Track) { - rowCandidateResoTrack(pVecD[0], pVecD[1], pVecD[2], - candV0Tr.px(), candV0Tr.py(), candV0Tr.pz(), - invMassReso, - 0); - } else { rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], invMassReso, invMassD, - invMassV0, - candV0Tr.cpa(), - candV0Tr.dca(), - candV0Tr.v0Radius(), - invMassD0); - rowCandidateResoIndices(collision.globalIndex(), - candD.globalIndex(), - candV0Tr.globalIndex()); + invMassV0Tr, + signReso, + isWrongSign); + rowCandidateResoIndices2PrTrks(collision.globalIndex(), candD.globalIndex(), candV0Tr.globalIndex()); + registry.fill(HIST("hMassResoVsPt"), invMassReso, ptReso); + registry.fill(HIST("hMassDmesDauVsPt"), invMassD, candD.pt()); + registry.fill(HIST("hMassV0DauVsPt"), invMassV0Tr, candV0Tr.pt()); } - if constexpr (fillMl) { - mlScores(candD.mlScoreBkgMassHypo0(), candD.mlScorePromptMassHypo0(), candD.mlScoreNonpromptMassHypo0()); + } + // D0bar + if (TESTBIT(selectionFlag, D0Sel::selectedD0Bar)) { + invMassD = candD.invMassD0Bar(); + if constexpr (bachType == BachelorType::V0) { + signReso = 0; + if (cfgV0Cuts.v0Type == V0Type::K0s) { // K0s + invMassV0Tr = candV0Tr.invMassK0s(); + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassKPlus, MassPiPlus, MassK0Short}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0Bar, MassK0Short}); + } + } else if (cfgV0Cuts.v0Type == V0Type::Lambda) { // Lambda + if (candV0Tr.v0Type() == V0Type::Lambda) { + invMassV0Tr = candV0Tr.invMassLambda(); + isWrongSign = 1; + } else if (candV0Tr.v0Type() == V0Type::AntiLambda) { + invMassV0Tr = candV0Tr.invMassAntiLambda(); + } + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassKPlus, MassPiPlus, MassLambda}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0Bar, MassLambda}); + } + } + rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], + pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], + invMassReso, + invMassD, + invMassV0Tr, + signReso, + isWrongSign); + rowCandidateResoIndices2PrV0s(collision.globalIndex(), candD.globalIndex(), candV0Tr.globalIndex()); + registry.fill(HIST("hMassResoVsPt"), invMassReso, ptReso); + registry.fill(HIST("hMassDmesDauVsPt"), invMassD, candD.pt()); + registry.fill(HIST("hMassV0DauVsPt"), invMassV0Tr, candV0Tr.pt()); + } else if constexpr (bachType == BachelorType::Track) { + signReso = candV0Tr.sign(); + isWrongSign = candV0Tr.sign() > 0 ? 1 : 0; + if (cfgTrackCuts.massHypo == TrackType::Pion) { // Pion + invMassV0Tr = MassPiPlus; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassKPlus, MassPiPlus, MassPiPlus}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0Bar, MassPiPlus}); + } + } else if (cfgTrackCuts.massHypo == TrackType::Kaon) { // Kaon + invMassV0Tr = MassKPlus; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassKPlus, MassPiPlus, MassKPlus}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0Bar, MassKPlus}); + } + } else if (cfgTrackCuts.massHypo == TrackType::Proton) { // Proton + invMassV0Tr = MassProton; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassKPlus, MassPiPlus, MassProton}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0Bar, MassProton}); + } + } + rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], + pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], + invMassReso, + invMassD, + invMassV0Tr, + signReso, + isWrongSign); + rowCandidateResoIndices2PrTrks(collision.globalIndex(), candD.globalIndex(), candV0Tr.globalIndex()); + registry.fill(HIST("hMassResoVsPt"), invMassReso, ptReso); + registry.fill(HIST("hMassDmesDauVsPt"), invMassD, candD.pt()); + registry.fill(HIST("hMassV0DauVsPt"), invMassV0Tr, candV0Tr.pt()); } } } - } // main function + } + + template + void runCandidateCreation(Coll const& collision, + DRedTable const& candsD, + V0TrRedTable const& candsV0Tr) + { + // loop on D candidates + // LOG(info) << "Number of D candidates: " << candsD.size() << ", Number of V0/Track candidates: " << candsV0Tr.size(); + for (const auto& candD : candsD) { + // selection of D candidates + registry.fill(HIST("hSelections"), 1); + uint8_t selFlagD = selctionFlagBachD(candD); + if (selFlagD == 0) { + continue; + } + registry.fill(HIST("hSelections"), 1 + Selections::DSel); + std::vector dDaughtersIDs = {candD.prong0Id(), candD.prong1Id()}; + if constexpr (dType == DType::Dstar || dType == DType::Dplus) { + dDaughtersIDs.push_back(candD.prong2Id()); + } + // loop on V0 or track candidates + bool alreadyCounted{false}; + for (const auto& candV0Tr : candsV0Tr) { + if constexpr (bachType == BachelorType::V0) { // Case: V0 + if (rejectPairsWithCommonDaughter) { + if (std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0Tr.prong0Id()) != dDaughtersIDs.end() || std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0Tr.prong1Id()) != dDaughtersIDs.end()) { + continue; + } + } + if (!isV0Selected(candV0Tr)) { + continue; + } + if (!alreadyCounted) { + registry.fill(HIST("hSelections"), 1 + Selections::BachSel); + alreadyCounted = true; + } + } else if constexpr (bachType == BachelorType::Track) { // Case: Track + if (rejectPairsWithCommonDaughter) { + if (std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0Tr.globalIndex()) != dDaughtersIDs.end()) { + continue; + } + } + if (!isTrackSelected(candV0Tr)) { + continue; + } + if (!alreadyCounted) { + registry.fill(HIST("hSelections"), 1 + Selections::BachSel); + alreadyCounted = true; + } + } + // Filling of tables and histograms + fillOutputTables(collision, candD, candV0Tr, selFlagD); + } // end of loop on V0/Track candidates + } // end of loop on D candidates + } // end of function + // Process data with Mixed Event /// \tparam fillMl is a flag to Fill ML scores if present /// \tparam channel is the decay channel of the Resonance /// \param Coll is the reduced collisions table /// \param DRedTable is the D bachelors table /// \param V0TrRedTable is the V0/Track bachelors table - template + template void runCandidateCreationMixedEvent(Coll const& collisions, DRedTable const& candsD, V0TrRedTable const& candsV0Tr) { using BinningType = ColumnBinningPolicy; - BinningType corrBinning{{zPoolBins, multPoolBins}, true}; + BinningType corrBinning{{cfgMixedEvent.zPoolBins, cfgMixedEvent.multPoolBins}, true}; auto bachTuple = std::make_tuple(candsD, candsV0Tr); - Pair pairs{corrBinning, numberEventsMixed, numberEventsToSkip, collisions, bachTuple, &cache}; + Pair pairs{corrBinning, cfgMixedEvent.numberEventsMixed, cfgMixedEvent.numberEventsToSkip, collisions, bachTuple, &cache}; for (const auto& [collision1, bachDs, collision2, bachV0Trs] : pairs) { registry.fill(HIST("hNPvContCorr"), collision1.numContrib(), collision2.numContrib()); registry.fill(HIST("hZvertCorr"), collision1.posZ(), collision2.posZ()); for (const auto& [bachD, bachV0Tr] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(bachDs, bachV0Trs))) { // Apply analysis selections on D and V0 bachelors - if (!isDSelected(bachD) || !isV0Selected(bachV0Tr, bachD)) { + uint8_t selFlagD = selctionFlagBachD(bachD); + if (selFlagD == 0) { continue; } - // Retrieve D and V0 informations - float invMassD{0.}; - float invMassD0{0.}; - if (std::abs(bachD.dType()) == DType::Dplus) { - invMassD = bachD.invMassDplus(); - } - if (bachD.dType() == DType::Dstar) { - invMassD = bachD.invMassDstar(); - invMassD0 = bachD.invMassD0(); - } - if (bachD.dType() == (-1) * DType::Dstar) { - invMassD = bachD.invMassAntiDstar(); - invMassD0 = bachD.invMassD0Bar(); - } - std::array pVecD = {bachD.px(), bachD.py(), bachD.pz()}; - float invMassReso{0.}; - float invMassV0{0.}; - std::array pVecV0Tr = {bachV0Tr.px(), bachV0Tr.py(), bachV0Tr.pz()}; - float ptReso = RecoDecay::pt(RecoDecay::sumOfVec(pVecV0Tr, pVecD)); - switch (channel) { - case DecayChannel::Ds1ToDstarK0s: - invMassV0 = bachV0Tr.invMassK0s(); - invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDStar, MassK0Short}); - registry.fill(HIST("hMassDs1"), invMassReso, ptReso); - break; - case DecayChannel::Ds2StarToDplusK0s: - invMassV0 = bachV0Tr.invMassK0s(); - invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDPlus, MassK0Short}); - registry.fill(HIST("hMassDs2Star"), invMassReso, ptReso); - break; - case DecayChannel::XcToDplusLambda: - if (bachD.dType() > 0) { - invMassV0 = bachV0Tr.invMassLambda(); - } else { - invMassV0 = bachV0Tr.invMassAntiLambda(); - } - invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDPlus, MassLambda}); - registry.fill(HIST("hMassXcRes"), invMassReso, ptReso); - break; - case DecayChannel::LambdaDminus: - if (bachD.dType() < 0) { - invMassV0 = bachV0Tr.invMassLambda(); - } else { - invMassV0 = bachV0Tr.invMassAntiLambda(); - } - invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDPlus, MassLambda}); - registry.fill(HIST("hMassLambdaDminus"), invMassReso, ptReso); - break; - default: - break; - } - // Fill output table - rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], - pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], - invMassReso, - invMassD, - invMassV0, - bachV0Tr.cpa(), - bachV0Tr.dca(), - bachV0Tr.v0Radius(), - invMassD0); - rowCandidateResoIndices(collision1.globalIndex(), - bachD.globalIndex(), - bachV0Tr.globalIndex()); - if constexpr (fillMl) { - mlScores(bachD.mlScoreBkgMassHypo0(), bachD.mlScorePromptMassHypo0(), bachD.mlScoreNonpromptMassHypo0()); + if constexpr (bachType == BachelorType::V0) { + if (!isV0Selected(bachV0Tr)) { + continue; + } + } else if constexpr (bachType == BachelorType::Track) { + if (!isTrackSelected(bachV0Tr)) { + continue; + } } + fillOutputTables(collision1, bachD, bachV0Tr, selFlagD); } } } // runCandidateCreationMixedEvent // List of Process Functions - void processDs2StarToDplusK0s(aod::HfRedCollisions const& collisions, - aod::HfRed3PrNoTrks const& candsD, - aod::HfRedVzeros const&) + void process3ProngV0s(aod::HfRedCollisions const& collisions, + aod::HfRed3PrNoTrks const& candsD, + aod::HfRedVzeros const& candsV0) { for (const auto& collision : collisions) { auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); - auto k0sThisColl = candidatesK0s.sliceBy(candsV0PerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, k0sThisColl); + auto candsDThisColl = candsD.sliceBy(cands3PrPerCollision, thisCollId); + auto v0sThisColl = candsV0.sliceBy(candsV0PerCollision, thisCollId); + runCandidateCreation(collision, candsDThisColl, v0sThisColl); } } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs2StarToDplusK0s, "Process Ds2* candidates without ML info", true); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, process3ProngV0s, "Process resonances decaying in a 3 prong D meson and a V0", true); - void processDs2StarToDplusK0sWithMl(aod::HfRedCollisions const& collisions, - soa::Join const& candsD, - aod::HfRedVzeros const&) + void processDstarV0s(aod::HfRedCollisions const& collisions, + aod::HfRedDstarNoTrks const& candsD, + aod::HfRedVzeros const& candsV0) { for (const auto& collision : collisions) { auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollisionWithMl, thisCollId); - auto k0sThisColl = candidatesK0s.sliceBy(candsV0PerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, k0sThisColl); + auto candsDThisColl = candsD.sliceBy(candsDstarPerCollision, thisCollId); + auto v0sThisColl = candsV0.sliceBy(candsV0PerCollision, thisCollId); + runCandidateCreation(collision, candsDThisColl, v0sThisColl); } } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs2StarToDplusK0sWithMl, "Process Ds2* candidates with Ml info", false); - - void processDs2StarToDplusK0sMixedEvent(aod::HfRedCollisions const& collisions, - aod::HfRed3PrNoTrks const& candsD, - aod::HfRedVzeros const& candsV0) - { - runCandidateCreationMixedEvent(collisions, candsD, candsV0); - } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs2StarToDplusK0sMixedEvent, "Process Ds2Star mixed Event without ML", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDstarV0s, "Process resonances decaying in a Dstar meson and a V0", false); - void processDs2StarToDplusK0sMixedEventWithMl(aod::HfRedCollisions const& collisions, - HfRed3PrNoTrksWithMl const& candsD, - aod::HfRedVzeros const& candsV0) - { - runCandidateCreationMixedEvent(collisions, candsD, candsV0); - } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs2StarToDplusK0sMixedEventWithMl, "Process Ds2Star mixed Event with ML", false); - - void processDs1ToDstarK0s(aod::HfRedCollisions const& collisions, - aod::HfRed3PrNoTrks const& candsD, - aod::HfRedVzeros const&) + void process2PrV0s(aod::HfRedCollisions const& collisions, + aod::HfRed2PrNoTrks const& candsD, + aod::HfRedVzeros const& candsV0) { for (const auto& collision : collisions) { auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); - auto k0sThisColl = candidatesK0s.sliceBy(candsV0PerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, k0sThisColl); + auto candsDThisColl = candsD.sliceBy(cands2PrPerCollision, thisCollId); + auto v0sThisColl = candsV0.sliceBy(candsV0PerCollision, thisCollId); + runCandidateCreation(collision, candsDThisColl, v0sThisColl); } } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs1ToDstarK0s, "Process Ds1 candidates without Ml info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, process2PrV0s, "Process resonances decaying in a 2 prong D meson and a V0", false); - void processDs1ToDstarK0sWithMl(aod::HfRedCollisions const& collisions, - HfRed3PrNoTrksWithMl const& candsD, - aod::HfRedVzeros const&) + void process3ProngTracks(aod::HfRedCollisions const& collisions, + aod::HfRed3PrNoTrks const& candsD, + HfRedTrkNoParams const& candsTr) { for (const auto& collision : collisions) { auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollisionWithMl, thisCollId); - auto k0sThisColl = candidatesK0s.sliceBy(candsV0PerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, k0sThisColl); + auto candsDThisColl = candsD.sliceBy(cands3PrPerCollision, thisCollId); + auto trksThisColl = candsTr.sliceBy(candsTrackPerCollision, thisCollId); + runCandidateCreation(collision, candsDThisColl, trksThisColl); } } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs1ToDstarK0sWithMl, "Process Ds1 candidates with Ml info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, process3ProngTracks, "Process resonances decaying in a 3 prong D meson and a Track", false); - void processDs1ToDstarK0sMixedEvent(aod::HfRedCollisions const& collisions, - aod::HfRed3PrNoTrks const& candsD, - aod::HfRedVzeros const& candsV0) - { - runCandidateCreationMixedEvent(collisions, candsD, candsV0); - } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs1ToDstarK0sMixedEvent, "Process Ds1 mixed Event without ML", false); - - void processDs1ToDstarK0sMixedEventWithMl(aod::HfRedCollisions const& collisions, - HfRed3PrNoTrksWithMl const& candsD, - aod::HfRedVzeros const& candsV0) - { - runCandidateCreationMixedEvent(collisions, candsD, candsV0); - } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs1ToDstarK0sMixedEventWithMl, "Process Ds1 mixed Event with ML", false); - - void processXcToDplusLambda(aod::HfRedCollisions const& collisions, - aod::HfRed3PrNoTrks const& candsD, - aod::HfRedVzeros const&) + void processDstarTracks(aod::HfRedCollisions const& collisions, + aod::HfRedDstarNoTrks const& candsD, + HfRedTrkNoParams const& candsTr) { for (const auto& collision : collisions) { auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); - auto lambdaThisColl = candidatesLambda.sliceBy(candsV0PerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, lambdaThisColl); + auto candsDThisColl = candsD.sliceBy(candsDstarPerCollision, thisCollId); + auto trksThisColl = candsTr.sliceBy(candsTrackPerCollision, thisCollId); + runCandidateCreation(collision, candsDThisColl, trksThisColl); } } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processXcToDplusLambda, "Process Xc candidates without Ml info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDstarTracks, "Process resonances decaying in a Dstar meson and a Track", false); - void processXcToDplusLambdaWithMl(aod::HfRedCollisions const& collisions, - HfRed3PrNoTrksWithMl const& candsD, - aod::HfRedVzeros const&) + void process2PrTracks(aod::HfRedCollisions const& collisions, + aod::HfRed2PrNoTrks const& candsD, + HfRedTrkNoParams const& candsTr) { for (const auto& collision : collisions) { auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollisionWithMl, thisCollId); - auto lambdaThisColl = candidatesLambda.sliceBy(candsV0PerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, lambdaThisColl); + auto candsDThisColl = candsD.sliceBy(cands2PrPerCollision, thisCollId); + auto trksThisColl = candsTr.sliceBy(candsTrackPerCollision, thisCollId); + runCandidateCreation(collision, candsDThisColl, trksThisColl); } } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processXcToDplusLambdaWithMl, "Process Xc candidates with Ml info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, process2PrTracks, "Process resonances decaying in a 2 prong D meson and a Track", false); - void processLambdaDminus(aod::HfRedCollisions const& collisions, - aod::HfRed3PrNoTrks const& candsD, - aod::HfRedVzeros const&) + // Mixed Event Process Functions + void process3ProngV0sMixedEvent(aod::HfRedCollisions const& collisions, + aod::HfRed3PrNoTrks const& candsD, + aod::HfRedVzeros const& candsV0) { - for (const auto& collision : collisions) { - auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); - auto lambdaThisColl = candidatesLambda.sliceBy(candsV0PerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, lambdaThisColl); - } + runCandidateCreationMixedEvent(collisions, candsD, candsV0); } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processLambdaDminus, "Process LambdaDminus candidates without Ml info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, process3ProngV0sMixedEvent, "Process mixed events for resonances decaying in a 3 prong D meson and a V0", false); - void processLambdaDminusWithMl(aod::HfRedCollisions const& collisions, - HfRed3PrNoTrksWithMl const& candsD, - aod::HfRedVzeros const&) + void processDstarV0sMixedEvent(aod::HfRedCollisions const& collisions, + aod::HfRedDstarNoTrks const& candsD, + aod::HfRedVzeros const& candsV0) { - for (const auto& collision : collisions) { - auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollisionWithMl, thisCollId); - auto lambdaThisColl = candidatesLambda.sliceBy(candsV0PerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, lambdaThisColl); - } + runCandidateCreationMixedEvent(collisions, candsD, candsV0); } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processLambdaDminusWithMl, "Process LambdaDminus candidates with Ml info", false); - void processDstarTrack(aod::HfRedCollisions const& collisions, - aod::HfRed3PrNoTrks const& candsD, - aod::HfRedTrkNoParams const& candidatesTrack) + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDstarV0sMixedEvent, "Process mixed events for resonances decaying in a Dstar meson and a V0", false); + + void process2PrV0sMixedEvent(aod::HfRedCollisions const& collisions, + aod::HfRed2PrNoTrks const& candsD, + aod::HfRedVzeros const& candsV0) { - for (const auto& collision : collisions) { - auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); - auto trackThisColl = candidatesTrack.sliceBy(candsTrackPerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, trackThisColl); - } + runCandidateCreationMixedEvent(collisions, candsD, candsV0); } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDstarTrack, "Process DStar candidates without Ml info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, process2PrV0sMixedEvent, "Process mixed events for resonances decaying in a 2 prong D meson and a V0", false); - void processDstarTrackWithMl(aod::HfRedCollisions const& collisions, - HfRed3PrNoTrksWithMl const& candsD, - aod::HfRedTrkNoParams const& candidatesTrack) + void process3ProngTracksMixedEvent(aod::HfRedCollisions const& collisions, + aod::HfRed3PrNoTrks const& candsD, + HfRedTrkNoParams const& candsTr) { - for (const auto& collision : collisions) { - auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollisionWithMl, thisCollId); - auto trackThisColl = candidatesTrack.sliceBy(candsTrackPerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, trackThisColl); - } + runCandidateCreationMixedEvent(collisions, candsD, candsTr); } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDstarTrackWithMl, "Process DStar candidates with Ml info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, process3ProngTracksMixedEvent, "Process mixed events for resonances decaying in a 3 prong D meson and a Track", false); - void processD0Track(aod::HfRedCollisions const& collisions, - aod::HfRed2PrNoTrks const& candsD, - aod::HfRedTrkNoParams const& candidatesTrack) + void processDstarTracksMixedEvent(aod::HfRedCollisions const& collisions, + aod::HfRedDstarNoTrks const& candsD, + HfRedTrkNoParams const& candsTr) { - for (const auto& collision : collisions) { - auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsD0PerCollision, thisCollId); - auto trackThisColl = candidatesTrack.sliceBy(candsTrackPerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, trackThisColl); - } + runCandidateCreationMixedEvent(collisions, candsD, candsTr); } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processD0Track, "Process D0 candidates without Ml info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDstarTracksMixedEvent, "Process mixed events for resonances decaying in a Dstar meson and a Track", false); - void processD0TrackWithMl(aod::HfRedCollisions const& collisions, - HfRed2PrNoTrksWithMl const& candsD, - aod::HfRedTrkNoParams const& candidatesTrack) + void process2PrTracksMixedEvent(aod::HfRedCollisions const& collisions, + aod::HfRed2PrNoTrks const& candsD, + HfRedTrkNoParams const& candsTr) { - for (const auto& collision : collisions) { - auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsD0PerCollisionWithMl, thisCollId); - auto trackThisColl = candidatesTrack.sliceBy(candsTrackPerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, trackThisColl); - } + runCandidateCreationMixedEvent(collisions, candsD, candsTr); } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processD0TrackWithMl, "Process D0 candidates with Ml info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, process2PrTracksMixedEvent, "Process mixed events for resonances decaying in a 2 prong D meson and a Track", false); }; // struct HfCandidateCreatorCharmResoReduced @@ -731,14 +895,18 @@ struct HfCandidateCreatorCharmResoReducedExpressions { Produces rowResoMcRec; - using CandResoWithIndices = soa::Join; + using CandResoWithIndices2PrV0s = soa::Join; + using CandResoWithIndices2PrTrks = soa::Join; + using CandResoWithIndices3PrV0s = soa::Join; + using CandResoWithIndices3PrTrks = soa::Join; + using CandResoWithIndicesDstarV0s = soa::Join; + using CandResoWithIndicesDstarTrks = soa::Join; // Configurable axis ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "#it{p}_{T} (GeV/#it{c})"}; ConfigurableAxis axisInvMassReso{"axisInvMassReso", {400, 0.49f, 0.89f}, "inv. mass (DV_{0}) (GeV/#it{c}^{2})"}; ConfigurableAxis axisInvMassProng0{"axisInvMassProng0", {200, 0.14, 0.17}, "inv. mass (D) (GeV/#it{c}^{2})"}; ConfigurableAxis axisInvMassProng1{"axisInvMassProng1", {200, 0.47, 0.53}, "inv. mass ({V}_{0}) (GeV/#it{c}^{2})"}; - ConfigurableAxis axisInvMassD0{"axisInvMassD0", {200, 1.65, 2.05}, "inv. mass ({V}_{0}) (GeV/#it{c}^{2})"}; ConfigurableAxis axisDebug{"axisDebug", {16, -0.5, 15.5}, "MC debug flag"}; ConfigurableAxis axisOrigin{"axisOrigin", {3, -0.5, 2.5}, "MC origin flag"}; HistogramRegistry registry{"registry"}; @@ -749,64 +917,83 @@ struct HfCandidateCreatorCharmResoReducedExpressions { registry.add("hMassMcMatchedIncomplete", "Reso MC candidates Matched with generate particle w. Invcomplete decay;m (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisInvMassReso, axisPt}}); registry.add("hMassMcUnmatched", "Reso MC candidates NOT Matched with generate particle;m (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisInvMassReso, axisPt}}); registry.add("hMassMcNoEntry", "Reso MC candidates w.o. entry in MC Reco table;m (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisInvMassReso, axisPt}}); - registry.add("hMassMcMatchedVsBach0Mass", "Reso MC candidates Matched with generate particle;m (GeV/#it{c}^{2}); m (GeV/#it{c}^{2})", {HistType::kTH2F, {axisInvMassReso, axisInvMassProng0}}); - registry.add("hMassMcUnmatchedVsBach0Mass", "Reso MC candidates Matched with generate particle w. Invcomplete decay;m (GeV/#it{c}^{2}); m (GeV/#it{c}^{2})", {HistType::kTH2F, {axisInvMassReso, axisInvMassProng0}}); - registry.add("hMassMcMatchedVsBach1Mass", "Reso MC candidates NOT Matched with generate particle;m (GeV/#it{c}^{2}); m (GeV/#it{c}^{2})", {HistType::kTH2F, {axisInvMassReso, axisInvMassProng1}}); - registry.add("hMassMcUnmatchedVsBach1Mass", "Reso MC candidates Matched with generate particle w. Invcomplete decay;m (GeV/#it{c}^{2}); m (GeV/#it{c}^{2})", {HistType::kTH2F, {axisInvMassReso, axisInvMassProng1}}); - registry.add("hMassMcMatchedVsD0Mass", "Reso MC candidates NOT Matched with generate particle;m (GeV/#it{c}^{2}); m (GeV/#it{c}^{2})", {HistType::kTH2F, {axisInvMassReso, axisInvMassD0}}); - registry.add("hMassMcUnmatchedVsD0Mass", "Reso MC candidates Matched with generate particle w. Invcomplete decay;m (GeV/#it{c}^{2}); m (GeV/#it{c}^{2})", {HistType::kTH2F, {axisInvMassReso, axisInvMassD0}}); - registry.add("hMassMcUnmatchedVsDebug", "Reso MC candidates NOT Matched with generate particle;m (GeV/#it{c}^{2});debug flag", {HistType::kTH2F, {axisInvMassReso, axisDebug}}); - registry.add("hSparseUnmatchedDebug", "THn for debug of MC matching and Correlated BKG study", HistType::kTHnSparseF, {axisInvMassReso, axisPt, axisInvMassProng0, axisInvMassProng1, axisInvMassD0, axisDebug, axisOrigin}); } /// Fill candidate information at MC reconstruction level - /// \param rowsDV0McRec MC reco information on DPi pairs + /// \param rowsMcRec MC reco information on DPi pairs /// \param candsReso prong global indices of B0 candidates - template - void fillResoMcRec(McRec const& rowsDV0McRec, CandResoWithIndices const& candsReso) + template + void fillResoMcRec(McRec const& rowsMcRec, CandResoWithIndices const& candsReso) { for (const auto& candReso : candsReso) { bool filledMcInfo{false}; - for (const auto& rowDV0McRec : rowsDV0McRec) { + for (const auto& rowDV0McRec : rowsMcRec) { if ((rowDV0McRec.prong0Id() != candReso.prong0Id()) || (rowDV0McRec.prong1Id() != candReso.prong1Id())) { continue; } - rowResoMcRec(rowDV0McRec.flagMcMatchRec(), rowDV0McRec.debugMcRec(), rowDV0McRec.origin(), rowDV0McRec.ptMother()); + rowResoMcRec(rowDV0McRec.flagMcMatchRec(), + rowDV0McRec.flagMcMatchRecD(), + rowDV0McRec.flagMcMatchChanD(), + rowDV0McRec.debugMcRec(), + rowDV0McRec.origin(), + rowDV0McRec.ptGen(), + rowDV0McRec.invMassGen()); filledMcInfo = true; - if (std::abs(rowDV0McRec.flagMcMatchRec()) == DecayTypeMc::Ds1ToDStarK0ToD0PiK0s || std::abs(rowDV0McRec.flagMcMatchRec()) == DecayTypeMc::Ds2StarToDplusK0sToPiKaPiPiPi || - std::abs(rowDV0McRec.flagMcMatchRec()) == DecayTypeMc::Ds1ToDStarK0ToD0PiK0sOneMu || std::abs(rowDV0McRec.flagMcMatchRec()) == DecayTypeMc::Ds2StarToDplusK0sOneMu) { + if (std::abs(rowDV0McRec.flagMcMatchRec()) > 0 && + !TESTBIT(rowDV0McRec.debugMcRec(), hf_decay::hf_cand_reso::PartialMatchMc::ResoPartlyMatched)) { registry.fill(HIST("hMassMcMatched"), candReso.invMass(), candReso.pt()); - registry.fill(HIST("hMassMcMatchedVsBach0Mass"), candReso.invMass(), candReso.invMassProng0() - candReso.invMassD0()); - registry.fill(HIST("hMassMcMatchedVsBach1Mass"), candReso.invMass(), candReso.invMassProng1()); - registry.fill(HIST("hMassMcMatchedVsD0Mass"), candReso.invMass(), candReso.invMassD0()); - - } else if (std::abs(rowDV0McRec.flagMcMatchRec()) == DecayTypeMc::Ds1ToDStarK0ToD0NoPiK0sPart || std::abs(rowDV0McRec.flagMcMatchRec()) == DecayTypeMc::Ds1ToDStarK0ToDPlusPi0K0s) { + } else if (std::abs(rowDV0McRec.flagMcMatchRec()) > 0 && + TESTBIT(rowDV0McRec.debugMcRec(), hf_decay::hf_cand_reso::PartialMatchMc::ResoPartlyMatched)) { registry.fill(HIST("hMassMcMatchedIncomplete"), candReso.invMass(), candReso.pt()); } else { registry.fill(HIST("hMassMcUnmatched"), candReso.invMass(), candReso.pt()); - registry.fill(HIST("hMassMcUnmatchedVsBach0Mass"), candReso.invMass(), candReso.invMassProng0() - candReso.invMassD0()); - registry.fill(HIST("hMassMcUnmatchedVsBach1Mass"), candReso.invMass(), candReso.invMassProng1()); - registry.fill(HIST("hMassMcUnmatchedVsD0Mass"), candReso.invMass(), candReso.invMassD0()); - registry.fill(HIST("hMassMcUnmatchedVsDebug"), candReso.invMass(), rowDV0McRec.debugMcRec()); - registry.fill(HIST("hSparseUnmatchedDebug"), candReso.invMass(), candReso.pt(), candReso.invMassProng0() - candReso.invMassD0(), candReso.invMassProng1(), candReso.invMassD0(), rowDV0McRec.debugMcRec(), rowDV0McRec.origin()); } - break; } if (!filledMcInfo) { // protection to get same size tables in case something went wrong: we created a candidate that was not preselected in the D-Pi creator - rowResoMcRec(0, -1, -1, -1.f); + rowResoMcRec(0, 0, 0, 0, 0, -1.f, -1.f); registry.fill(HIST("hMassMcNoEntry"), candReso.invMass(), candReso.pt()); } } } - void processMc(aod::HfMcRecRedDV0s const& rowsDV0McRec, CandResoWithIndices const& candsReso) + void processDstarV0Mc(aod::HfDstarV0McRec const& rowsMcRec, CandResoWithIndicesDstarV0s const& candsReso) + { + fillResoMcRec(rowsMcRec, candsReso); + } + PROCESS_SWITCH(HfCandidateCreatorCharmResoReducedExpressions, processDstarV0Mc, "Process resonances to Dstar V0 MC", false); + + void processDstarTrackMc(aod::HfDstarTrkMcRec const& rowsMcRec, CandResoWithIndicesDstarTrks const& candsReso) + { + fillResoMcRec(rowsMcRec, candsReso); + } + PROCESS_SWITCH(HfCandidateCreatorCharmResoReducedExpressions, processDstarTrackMc, "Process resonances to Dstar track MC", false); + + void process2PrV0Mc(aod::Hf2PrV0McRec const& rowsMcRec, CandResoWithIndices2PrV0s const& candsReso) + { + fillResoMcRec(rowsMcRec, candsReso); + } + PROCESS_SWITCH(HfCandidateCreatorCharmResoReducedExpressions, process2PrV0Mc, "Process resonances to D0 V0 MC", false); + + void process2PrTrackMc(aod::Hf2PrTrkMcRec const& rowsMcRec, CandResoWithIndices2PrTrks const& candsReso) + { + fillResoMcRec(rowsMcRec, candsReso); + } + PROCESS_SWITCH(HfCandidateCreatorCharmResoReducedExpressions, process2PrTrackMc, "Process resonances to D0 track MC", false); + + void process3PrV0Mc(aod::Hf3PrV0McRec const& rowsMcRec, CandResoWithIndices3PrV0s const& candsReso) + { + fillResoMcRec(rowsMcRec, candsReso); + } + PROCESS_SWITCH(HfCandidateCreatorCharmResoReducedExpressions, process3PrV0Mc, "Process resonances to Dplus V0 MC", false); + + void process3PrTrackMc(aod::Hf3PrTrkMcRec const& rowsMcRec, CandResoWithIndices3PrTrks const& candsReso) { - fillResoMcRec(rowsDV0McRec, candsReso); + fillResoMcRec(rowsMcRec, candsReso); } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReducedExpressions, processMc, "Process MC", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReducedExpressions, process3PrTrackMc, "Process resonances to Dplus track MC", false); - void processDummy(CandResoWithIndices const&) {} + void processDummy(aod::HfCandCharmReso const&) {} PROCESS_SWITCH(HfCandidateCreatorCharmResoReducedExpressions, processDummy, "Process dummy", true); }; diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx index 3c51c84a6d2..a2584dc5b06 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx @@ -16,6 +16,7 @@ /// \author Fabrizio Grosa , CERN #include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/D2H/Utils/utilsRedDataFormat.h" @@ -23,6 +24,7 @@ #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGHF/Utils/utilsMcMatching.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" @@ -48,6 +50,7 @@ #include #include #include +#include #include #include @@ -63,6 +66,7 @@ #include #include #include +#include #include using namespace o2; @@ -71,7 +75,6 @@ using namespace o2::aod; using namespace o2::constants::physics; using namespace o2::framework; using namespace o2::framework::expressions; - // event types enum Event : uint8_t { Processed = 0, @@ -80,12 +83,6 @@ enum Event : uint8_t { kNEvent }; -enum DecayChannel : uint8_t { - DstarV0 = 0, - DplusV0, - DstarTrack -}; - enum BachelorType : uint8_t { K0s = 0, Lambda, @@ -110,25 +107,6 @@ enum D0Sel : uint8_t { selectedD0Bar }; -enum DecayTypeMc : uint8_t { - Ds1ToDstarK0ToD0PiK0s = 1, - Ds2StarToDplusK0sToPiKaPiPiPi, - Ds1ToDstarK0ToDplusPi0K0s, - Ds1ToDstarK0ToD0PiK0sPart, - Ds1ToDstarK0ToD0NoPiK0sPart, - Ds1ToDstarK0ToD0PiK0sOneMu, - Ds2StarToDplusK0sOneMu -}; - -enum PartialMatchMc : uint8_t { - K0Matched = 0, - D0Matched, - DstarMatched, - DplusMatched, - K0MuMatched, - DstarMuMatched -}; - /// Creation of D-V0 pairs struct HfDataCreatorCharmResoReduced { @@ -140,12 +118,18 @@ struct HfDataCreatorCharmResoReduced { Produces hfTrackNoParam; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h Produces hfCandD3Pr; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h Produces hfCandD2Pr; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h + Produces hfCandDstar; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h // ML optional Tables Produces hfCandD3PrMl; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h Produces hfCandD2PrMl; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h // MC Tables - Produces rowHfDV0McRecReduced; Produces rowHfResoMcGenReduced; + Produces rowHf3PrV0McRecReduced; + Produces rowHfDstarV0McRecReduced; + Produces rowHf2PrV0McRecReduced; + Produces rowHf3PrTrkMcRecReduced; + Produces rowHfDstarTrkMcRecReduced; + Produces rowHf2PrTrkMcRecReduced; // selection D struct : ConfigurableGroup { @@ -205,9 +189,11 @@ struct HfDataCreatorCharmResoReduced { Configurable propagateV0toPV{"propagateV0toPV", false, "Enable or disable V0 propagation to V0"}; Configurable doMcRecQa{"doMcRecQa", true, "Fill QA histograms for Mc matching"}; Configurable rejectPairsWithCommonDaughter{"rejectPairsWithCommonDaughter", true, "flag to reject already at this stage the pairs that share a daughter track"}; + Configurable rejectCollisionsWithBadEvSel{"rejectCollisionsWithBadEvSel", true, "flag to reject collisions with bad event selection"}; HfHelper hfHelper; o2::hf_evsel::HfEventSelection hfEvSel; + o2::hf_evsel::HfEventSelectionMc hfEvSelMc; // CCDB service o2::ccdb::CcdbApi ccdbApi; @@ -256,15 +242,29 @@ struct HfDataCreatorCharmResoReduced { std::array pVectorProng2; } varUtils; + // Dplus using CandsDplusFiltered = soa::Filtered>; using CandsDplusFilteredWithMl = soa::Filtered>; + using CandsDplusFilteredWithMc = soa::Filtered>; + using CandsDplusFilteredWithMlAndMc = soa::Filtered>; + // Dstar using CandsDstarFiltered = soa::Filtered>; using CandsDstarFilteredWithMl = soa::Filtered>; + using CandsDstarFilteredWithMc = soa::Filtered>; + using CandsDstarFilteredWithMlAndMc = soa::Filtered>; + // D0 using CandsD0Filtered = soa::Filtered>; using CandsD0FilteredWithMl = soa::Filtered>; + using CandsD0FilteredWithMc = soa::Filtered>; + using CandsD0FilteredWithMlAndMc = soa::Filtered>; + // Tracks using TracksWithPID = soa::Join; + using TracksWithPIDAndMC = soa::Join; using TracksIUWithPID = soa::Join; using TracksIUWithPIDAndMC = soa::Join; + // Collisions MC + using BCsInfo = soa::Join; + using McCollisionsNoCents = soa::Join; Filter filterSelectDplus = (aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= cfgDmesCuts.selectionFlagDplus); Filter filterSelectedCandDstar = (aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == cfgDmesCuts.selectionFlagDstarToD0Pi); @@ -278,10 +278,12 @@ struct HfDataCreatorCharmResoReduced { Preslice candsD0PerCollisionWithMl = aod::hf_cand::collisionId; Preslice candsV0PerCollision = aod::v0::collisionId; Preslice trackIndicesPerCollision = aod::track_association::collisionId; + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; + PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; HistogramRegistry registry{"registry"}; - void init(InitContext const&) + void init(InitContext& initContext) { // histograms constexpr int kNBinsEvents = kNEvent; @@ -311,10 +313,11 @@ struct HfDataCreatorCharmResoReduced { registry.add("hMassVsPtK0s", "K0^{s} candidates;#it{p}_{T} (GeV/#it{c});inv. mass (#pi^{#plus}#pi^{#minus}) (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassKzero}}); registry.add("hMassVsPtLambda", "Lambda candidates;#it{p}_{T} (GeV/#it{c});inv. mass (p #pi^{#minus}) (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassLambda}}); registry.add("hdEdxVsP", "Tracks;#it{p} (GeV/#it{c});d#it{E}/d#it{x};entries", {HistType::kTH2D, {axisP, axisDeDx}}); - registry.add("hDType", "D selection flag", {HistType::kTH1D, {{5, -2.5, 2.5}}}); - if (doprocessD0V0 || doprocessD0Track || doprocessD0V0AndTrack || doprocessD0V0WithMl || doprocessD0TrackWithMl || doprocessD0V0AndTrackWithMl) { + if (doprocessD0V0 || doprocessD0Track || doprocessD0V0AndTrack || doprocessD0V0WithMl || doprocessD0TrackWithMl || doprocessD0V0AndTrackWithMl || + doprocessD0V0MC || doprocessD0TrackMC || doprocessD0V0AndTrackMC || doprocessD0V0MCWithMl || doprocessD0TrackMCWithMl || doprocessD0V0AndTrackMCWithMl) { registry.add("hMassVsPtD0All", "D0 candidates (all, regardless the pairing with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassD0}}); + registry.add("hMassVsPtD0BarAll", "D0bar candidates (all, regardless the pairing with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassD0}}); registry.add("hMassVsPtD0Paired", "D0 candidates (paired with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassD0}}); registry.add("hMassVsPtD0BarPaired", "D0 candidates (paired with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassD0}}); registry.add("hMassD0Pi", "D0Pi candidates; m_{D^{0}#pi^{+}} - m_{D^{0}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToPi}}); @@ -322,7 +325,8 @@ struct HfDataCreatorCharmResoReduced { registry.add("hMassD0Proton", "D0Proton candidates; m_{D^{0}p} - m_{D^{0}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToPr}}); registry.add("hMassD0Lambda", "D0Lambda candidates; m_{D^{0}#Lambda} - m_{D^{0}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToLambda}}); } - if (doprocessDstarV0 || doprocessDstarTrack || doprocessDstarV0AndTrack || doprocessDstarV0WithMl || doprocessDstarTrackWithMl || doprocessDstarV0AndTrackWithMl || doprocessDstarV0MCWithMl) { + if (doprocessDstarV0 || doprocessDstarTrack || doprocessDstarV0AndTrack || doprocessDstarV0WithMl || doprocessDstarTrackWithMl || doprocessDstarV0AndTrackWithMl || + doprocessDstarV0MC || doprocessDstarTrackMC || doprocessDstarV0AndTrackMC || doprocessDstarV0MCWithMl || doprocessDstarTrackMCWithMl || doprocessDstarV0AndTrackMCWithMl) { registry.add("hMassVsPtDstarAll", "Dstar candidates (all, regardless the pairing with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDstar}}); registry.add("hMassVsPtDstarPaired", "Dstar candidates (paired with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDstar}}); registry.add("hMassDstarPi", "DstarPi candidates; m_{D^{*+}#pi^{-}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToPi}}); @@ -331,7 +335,8 @@ struct HfDataCreatorCharmResoReduced { registry.add("hMassDstarK0s", "DstarK0s candidates; m_{D^{*}K^{0}_{S}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToK}}); registry.add("hMassDstarLambda", "DstarLambda candidates; m_{D^{*}#Lambda} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToLambda}}); } - if (doprocessDplusV0 || doprocessDplusV0AndTrack || doprocessDplusV0WithMl || doprocessDplusTrackWithMl || doprocessDplusV0AndTrackWithMl || doprocessDplusV0MCWithMl) { + if (doprocessDplusV0 || doprocessDplusTrack || doprocessDplusV0AndTrack || doprocessDplusV0WithMl || doprocessDplusTrackWithMl || doprocessDplusV0AndTrackWithMl || + doprocessDplusV0MC || doprocessDplusTrackMC || doprocessDplusV0AndTrackMC || doprocessDplusV0MCWithMl || doprocessDplusTrackMCWithMl || doprocessDplusV0AndTrackMCWithMl) { registry.add("hMassVsPtDplusAll", "Dplus candidates (all, regardless the pairing with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); registry.add("hMassVsPtDplusPaired", "Dplus candidates (paired with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); registry.add("hMassDplusK0s", "DplusK0s candidates; m_{D^{+}K^{0}_{S}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToK}}); @@ -340,39 +345,19 @@ struct HfDataCreatorCharmResoReduced { registry.add("hMassDplusProton", "DplusProton candidates; m_{D^{+}p} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToPr}}); registry.add("hMassDplusLambda", "DplusLambda candidates; m_{D^{+}#Lambda} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToLambda}}); } - if (doprocessDplusV0MCWithMl) { + if (doprocessD0V0MC || doprocessD0TrackMC || doprocessD0V0AndTrackMC || doprocessD0V0MCWithMl || doprocessD0TrackMCWithMl || doprocessD0V0AndTrackMCWithMl || + doprocessDstarV0MC || doprocessDstarTrackMC || doprocessDstarV0AndTrackMC || doprocessDstarV0MCWithMl || doprocessDstarTrackMCWithMl || doprocessDstarV0AndTrackMCWithMl || + doprocessDplusV0MC || doprocessDplusTrackMC || doprocessDplusV0AndTrackMC || doprocessDplusV0MCWithMl || doprocessDplusTrackMCWithMl || doprocessDplusV0AndTrackMCWithMl) { // MC Rec - registry.add("hMCRecCounter", "Number of Reconstructed MC Matched candidates per channel", {HistType::kTH1D, {{17, -8.5, 8.5}}}); - registry.add("hMCRecDebug", "Debug of MC Reco", {HistType::kTH1D, {{16, -0.5, 15.5}}}); + registry.add("hMCRecCounter", "Number of Reconstructed MC Matched candidates per channel", {HistType::kTH1D, {{31, -15.5, 15.5}}}); + registry.add("hMCRecDebug", "Debug of MC Reco", {HistType::kTH1D, {{551, -0.5, 550.5}}}); registry.add("hMCRecOrigin", "Origin of Matched particles", {HistType::kTH1D, {{3, -0.5, 2.5}}}); registry.add("hMCRecMassGen", "Generated inv. mass of resoncances", {HistType::kTH1D, {{2000, 1.8, 3.8}}}); + registry.add("hMCRecCharmDau", "Charm daughter flag", {HistType::kTH1D, {{57, -28.5, 28.5}}}); // MC Gen registry.add("hMCGenCounter", "Number of Generated particles; Decay Channel Flag; pT [GeV/c]", {HistType::kTH2D, {{17, -8.5, 8.5}, {100, 0, 50}}}); - registry.add("hMCSignCounter", "Sign of Generated particles", {HistType::kTH1D, {{3, -1.5, 1.5}}}); registry.add("hMCGenOrigin", "Origin of Generated particles", {HistType::kTH1D, {{3, -0.5, 2.5}}}); - registry.add("hMCOriginCounterWrongDecay", "Origin of Generated particles in Wrong decay", {HistType::kTH1D, {{3, -0.5, 2.5}}}); - } - - if (doMcRecQa) { - registry.add("hMassVsPtK0Matched", "K0s candidates Matched ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassKzero}}); - registry.add("hMassVsPtD0Matched", "D0 candidates Matched ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); - registry.add("hMassVsPtDstarMatched", "Dstar candidates Matched ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDstar}}); - registry.add("hMassVsPtDplusMatched", "Dplus candidates Matched ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); - registry.add("hMassVsPtDs1Matched", "Ds1 candidates Matched ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDsj}}); - registry.add("hMassVsPtDs2StarMatched", "Ds2Star candidates Matched ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDsj}}); - registry.add("hMassVsPtK0MatchedPiToMu", "K0s candidates Matched with PiToMu decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassKzero}}); - registry.add("hMassVsPtD0MatchedPiToMu", "D0 candidates Matched with PiToMu decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); - registry.add("hMassVsPtDstarMatchedPiToMu", "Dstar candidates Matched with PiToMu decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDstar}}); - registry.add("hMassVsPtDplusMatchedPiToMu", "Dplus candidates Matched with PiToMu decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); - registry.add("hMassVsPtDs1MatchedPiToMu", "Ds1 candidates Matched with PiToMu decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDsj}}); - registry.add("hMassVsPtDs2StarMatchedPiToMu", "Ds2Star candidates Matched with PiToMu decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDsj}}); - registry.add("hMassVsPtD0MatchedKaToPi", "D0 candidates Matched with KaToPi decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); - registry.add("hMassVsPtDstarMatchedKaToPi", "Dstar candidates Matched with KaToPi decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDstar}}); - registry.add("hMassVsPtDplusMatchedKaToPi", "Dplus candidates Matched with KaToPi decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); - registry.add("hMassVsPtDs1MatchedKaToPi", "Ds1 candidates Matched with KaToPi decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDsj}}); - registry.add("hMassVsPtDs2StarMatchedKaToPi", "Ds2Star candidates Matched with KaToPi decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDsj}}); } - // Configure CCDB access ccdb->setURL(ccdbUrl.value); ccdb->setCaching(true); @@ -395,6 +380,15 @@ struct HfDataCreatorCharmResoReduced { // init HF event selection helper hfEvSel.init(registry); + + const auto& workflows = initContext.services().get(); + for (const DeviceSpec& device : workflows.devices) { + if (device.name.compare("hf-data-creator-charm-reso-reduced") == 0) { + // init HF event selection helper + hfEvSelMc.init(device, registry); + break; + } + } } /// Basic track quality selections for V0 daughters @@ -449,7 +443,6 @@ struct HfDataCreatorCharmResoReduced { { auto trackPos = dauTracks[0]; auto trackNeg = dauTracks[1]; - // single-tracks selection if (!selectV0Daughter(trackPos, dDaughtersIds) || !selectV0Daughter(trackNeg, dDaughtersIds)) return false; @@ -471,7 +464,6 @@ struct HfDataCreatorCharmResoReduced { try { nCand = fitter.process(trackPosCov, trackNegCov); } catch (...) { - LOG(error) << "Exception caught in DCA fitter process call!"; return false; } if (nCand == 0) { @@ -482,9 +474,9 @@ struct HfDataCreatorCharmResoReduced { auto& trackNegProp = fitter.getTrack(1); trackPosProp.getPxPyPzGlo(candidateV0.momPos); trackNegProp.getPxPyPzGlo(candidateV0.momNeg); - for (int i = 0; i < 3; ++i) { // o2-linter: disable=magic-number (loop on xyz) - candidateV0.mom[i] = candidateV0.momPos[i] + candidateV0.momNeg[i]; - } + + candidateV0.mom = RecoDecay::pVec(candidateV0.momPos, candidateV0.momNeg); + candidateV0.pT = std::hypot(candidateV0.mom[0], candidateV0.mom[1]); // topological selections: // v0 eta @@ -503,9 +495,8 @@ struct HfDataCreatorCharmResoReduced { if (candidateV0.radius < cfgV0Cuts.radiusMin) { return false; } - for (int i = 0; i < 3; i++) { // o2-linter: disable=magic-number (loop on xyz) - candidateV0.pos[i] = vtx[i]; - } + std::copy(vtx.begin(), vtx.end(), candidateV0.pos.begin()); + // v0 DCA to primary vertex candidateV0.dcaV0ToPv = calculateDCAStraightToPV( vtx[0], vtx[1], vtx[2], @@ -522,42 +513,41 @@ struct HfDataCreatorCharmResoReduced { if (candidateV0.cosPA < cfgV0Cuts.cosPa) { return false; } - // distinguish between K0s, and Lambda hypotesys - candidateV0.v0Type = {BIT(K0s) | BIT(Lambda) | BIT(AntiLambda)}; + candidateV0.v0Type = {BIT(BachelorType::K0s) | BIT(BachelorType::Lambda) | BIT(BachelorType::AntiLambda)}; // for lambda hypotesys define if its lambda or anti-lambda candidateV0.alpha = alphaAP(candidateV0.mom, candidateV0.momPos, candidateV0.momNeg); bool matter = candidateV0.alpha > 0; - CLRBIT(candidateV0.v0Type, matter ? AntiLambda : Lambda); + CLRBIT(candidateV0.v0Type, matter ? BachelorType::AntiLambda : BachelorType::Lambda); auto massPos = matter ? o2::constants::physics::MassProton : o2::constants::physics::MassPionCharged; auto massNeg = matter ? o2::constants::physics::MassPionCharged : o2::constants::physics::MassProton; // mass hypotesis candidateV0.mLambda = RecoDecay::m(std::array{candidateV0.momPos, candidateV0.momNeg}, std::array{massPos, massNeg}); candidateV0.mK0Short = RecoDecay::m(std::array{candidateV0.momPos, candidateV0.momNeg}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged}); if (std::fabs(candidateV0.mK0Short - MassK0) > cfgV0Cuts.deltaMassK0s) { - CLRBIT(candidateV0.v0Type, K0s); + CLRBIT(candidateV0.v0Type, BachelorType::K0s); } if (std::fabs(candidateV0.mLambda - MassLambda0) > cfgV0Cuts.deltaMassLambda) { - CLRBIT(candidateV0.v0Type, Lambda); - CLRBIT(candidateV0.v0Type, AntiLambda); + CLRBIT(candidateV0.v0Type, BachelorType::Lambda); + CLRBIT(candidateV0.v0Type, BachelorType::AntiLambda); } // PID - if (TESTBIT(candidateV0.v0Type, K0s)) { + if (TESTBIT(candidateV0.v0Type, BachelorType::K0s)) { if ((trackPos.hasTPC() && std::fabs(trackPos.tpcNSigmaPi()) > cfgV0Cuts.nSigmaTpc) || (trackNeg.hasTPC() && std::fabs(trackNeg.tpcNSigmaPi()) > cfgV0Cuts.nSigmaTpc)) - CLRBIT(candidateV0.v0Type, K0s); + CLRBIT(candidateV0.v0Type, BachelorType::K0s); } - if (TESTBIT(candidateV0.v0Type, Lambda)) { + if (TESTBIT(candidateV0.v0Type, BachelorType::Lambda)) { if ((trackPos.hasTPC() && std::fabs(trackPos.tpcNSigmaPr()) > cfgV0Cuts.nSigmaTpc) || (trackPos.hasTOF() && std::fabs(trackPos.tofNSigmaPr()) > cfgV0Cuts.nSigmaTofPr) || (trackNeg.hasTPC() && std::fabs(trackNeg.tpcNSigmaPi()) > cfgV0Cuts.nSigmaTpc)) - CLRBIT(candidateV0.v0Type, Lambda); + CLRBIT(candidateV0.v0Type, BachelorType::Lambda); } - if (TESTBIT(candidateV0.v0Type, AntiLambda)) { + if (TESTBIT(candidateV0.v0Type, BachelorType::AntiLambda)) { if ((trackPos.hasTPC() && std::fabs(trackPos.tpcNSigmaPi()) > cfgV0Cuts.nSigmaTpc) || (trackNeg.hasTPC() && std::fabs(trackNeg.tpcNSigmaPr()) > cfgV0Cuts.nSigmaTpc) || (trackNeg.hasTOF() && std::fabs(trackNeg.tofNSigmaPr()) > cfgV0Cuts.nSigmaTofPr)) - CLRBIT(candidateV0.v0Type, AntiLambda); + CLRBIT(candidateV0.v0Type, BachelorType::AntiLambda); } if (candidateV0.v0Type == 0) { return false; @@ -572,11 +562,9 @@ struct HfDataCreatorCharmResoReduced { template bool isTrackSelected(const Tr& track, const std::array& dDaughtersIds) { - if (rejectPairsWithCommonDaughter && std::find(dDaughtersIds.begin(), dDaughtersIds.end(), track.globalIndex()) != dDaughtersIds.end()) { return false; } - switch (cfgSingleTrackCuts.setTrackSelections) { case 1: if (!track.isGlobalTrackWoDCA()) { @@ -594,254 +582,414 @@ struct HfDataCreatorCharmResoReduced { } break; } - if (track.pt() < cfgSingleTrackCuts.minPt) { return false; } - if (std::abs(track.eta()) > cfgSingleTrackCuts.maxEta) { return false; } - if (!track.hasTPC()) { return false; } - bool isPion = std::abs(track.tpcNSigmaPi()) < cfgSingleTrackCuts.maxNsigmaTpcPi; bool isKaon = std::abs(track.tpcNSigmaKa()) < cfgSingleTrackCuts.maxNsigmaTpcKa; bool isProton = std::abs(track.tpcNSigmaPr()) < cfgSingleTrackCuts.maxNsigmaTpcPr; - if (!isPion && !isKaon && !isProton) { // we keep the track if is it compatible with at least one of the PID hypotheses selected return false; } - return true; } - /// Function for filling MC reco information in the tables - /// \param particlesMc is the table with MC particles - /// \param vecDaughtersReso is the vector with all daughter tracks (bachelor pion in last position) - /// \param indexHfCandCharm is the index of the charm-hadron bachelor in the reduced table - /// \param indexCandV0 is the index of the v0 bachelor in the reduced table - template - void fillMcRecoInfo(const PParticles& particlesMc, - const std::vector& vecDaughtersReso, - int& indexHfCandCharm, - int& indexCandV0) + template + int8_t getMatchingFlagV0(PParticles const& particlesMc, const std::array& arrDaughtersV0) { - // we check the MC matching to be stored - int8_t sign{0}; - int8_t signDstar{0}; - int8_t signDplus{0}; - int8_t signD0{0}; int8_t signV0{0}; - int8_t flag{0}; - int8_t debug{0}; - int8_t origin{0}; - int8_t nPiToMuReso{0}, nPiToMuV0, nPiToMuD0{0}, nPiToMuDstar{0}, nPiToMuDplus{0}; - int8_t nKaToPiReso{0}, nKaToPiV0, nKaToPiD0{0}, nKaToPiDstar{0}, nKaToPiDplus{0}; - std::vector idxBhadMothers{}; - float motherPt{-1.f}; - float invMassGen{-1.f}; - int indexRecReso{-1}, indexRecDstar{-1}, indexRecDplus{-1}, indexRecD0{-1}, indexRecK0{-1}, indexRecResoPartReco{-1}; + int indexRec{-1}; + int flagV0{0}; + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersV0, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signV0, 2); + if (indexRec > -1) { + flagV0 = hf_decay::hf_cand_reso::PartialMatchMc::K0Matched; + } else { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersV0, kLambda0, std::array{+kProton, -kPiPlus}, true, &signV0, 2); + if (indexRec > -1) { + flagV0 = signV0 * hf_decay::hf_cand_reso::PartialMatchMc::LambdaMatched; + } + } + return flagV0; // Placeholder, should return the actual flag based on matching logic + } + /// Function for filling MC reco information of DV0 candidates in the tables + /// \tparam dType is the D meson type (Dstar, Dplus or D0) + /// \param particlesMc is the table with MC particles + /// \param candCharmBach is the D meson candidate + /// \param bachelorV0 is the V0 candidate + /// \param tracks is the table with tracks + /// \param indexHfCandCharm is the index of the charm-hadron bachelor in the reduced table + /// \param indexCandV0TrBach is the index of the v0 bachelor in the reduced table + template + void fillMcRecoInfoDV0(PParticles const& particlesMc, + CCand const& candCharmBach, + BBachV0 const& bachelorV0, + Tr const& tracks, + int& indexHfCandCharm, + int64_t& indexCandV0Bach) + { + std::vector vecDaughtersReso{}; + int8_t sign{0}, nKinkedTracks{0}, origin{0}, flagCharmBach{0}, flagCharmBachInterm{0}, flagV0{0}, flagReso{0}; + int indexRec{-1}, debugMcRec{0}; + float ptGen{-1.f}, invMassGen{-1.f}; if constexpr (dType == DType::Dstar) { - // Ds1 → D* K0 → (D0 π+) K0s → ((K-π+) π+)(π+π-) - indexRecD0 = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1]}, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &signD0, 1, &nPiToMuD0, &nKaToPiD0); - indexRecK0 = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[3], vecDaughtersReso[4]}, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signV0, 2, &nPiToMuV0, &nKaToPiV0); - if (indexRecD0 > -1) { - indexRecDstar = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2]}, Pdg::kDStar, std::array{-kKPlus, +kPiPlus, +kPiPlus}, true, &signDstar, 2, &nPiToMuDstar, &nKaToPiDstar); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong0Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong1Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prongPiId())); + // Check if D* is matched + flagCharmBach = candCharmBach.flagMcMatchRec(); + if (std::abs(flagCharmBach) > 0) { + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::DstarMatched); + origin = candCharmBach.originMcRec(); } - if (indexRecD0 > -1 && indexRecDstar > -1 && indexRecK0 > -1) { - indexRecReso = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], vecDaughtersReso[3], vecDaughtersReso[4]}, Pdg::kDS1, std::array{+kPiPlus, -kKPlus, +kPiPlus, +kPiPlus, -kPiPlus}, true, &sign, 3, &nPiToMuReso, &nKaToPiReso); - if (indexRecReso > -1 && nPiToMuReso == 0 && nKaToPiReso == 0) { - flag = sign * DecayTypeMc::Ds1ToDstarK0ToD0PiK0s; - } else if (indexRecReso > -1 && nPiToMuReso >= 1 && nKaToPiReso == 0) { - flag = sign * DecayTypeMc::Ds1ToDstarK0ToD0PiK0sOneMu; - } + // Check if D0 is matched + flagCharmBachInterm = candCharmBach.flagMcMatchRecD0(); + if (std::abs(flagCharmBachInterm) > 0) { + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::D0Matched); } - - // Ds1+ not matched: we check if it is partially reco - if (indexRecReso < 0) { - indexRecResoPartReco = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], vecDaughtersReso[3], vecDaughtersReso[4]}, Pdg::kDS1, std::array{+kPiPlus, -kKPlus, +kPiPlus, +kPiPlus, -kPiPlus}, true, &sign, 3); - indexRecDplus = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2]}, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &signDplus, 2); - if (indexRecResoPartReco > -1) { // we look for decays of D* or D0 with more daughters - if (indexRecDstar < 0 && indexRecK0 > -1) { - auto indexRecDstarPartReco = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2]}, Pdg::kDStar, std::array{-kKPlus, +kPiPlus, +kPiPlus}, true, &signDstar, 3); - if (indexRecDstarPartReco > -1) { - if (indexRecDplus > -1) { // Ds1 -> D* K0s -> D+ π0 K0s - flag = sign * DecayTypeMc::Ds1ToDstarK0ToDplusPi0K0s; - } else { - auto indexRecD0PartReco = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1]}, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &signD0, 2); - if (indexRecD0PartReco > -1) { // Ds1 -> D* K0s -> D0 π+ K0s -> K- π+ π0 π+ K0s - flag = sign * DecayTypeMc::Ds1ToDstarK0ToD0PiK0sPart; - } - } - } + // Check if V0 is matched + vecDaughtersReso.push_back(tracks.rawIteratorAt(bachelorV0.posTrackId())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(bachelorV0.negTrackId())); + flagV0 = getMatchingFlagV0(particlesMc, std::array{vecDaughtersReso[3], vecDaughtersReso[4]}); + if (std::abs(flagV0) > 0) { + SETBIT(debugMcRec, std::abs(flagV0)); + } + // If both D* and K0s are matched, try to match resonance + if (std::abs(flagCharmBach) > 0 && flagV0 == hf_decay::hf_cand_reso::PartialMatchMc::K0Matched) { + std::array pdgCodesDaughters = {+kPiPlus, -kKPlus, +kPiPlus, +kPiPlus, -kPiPlus}; + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], vecDaughtersReso[3], vecDaughtersReso[4]}; + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDstarK0s) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + break; } - } else { // we look for D* not matched, but all the other ones yes, we check if we only lost the soft pion - if (indexRecD0 > -1 && indexRecK0 > -1 && indexRecDstar < 0) { - indexRecResoPartReco = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[3], vecDaughtersReso[4]}, Pdg::kDS1, std::array{+kPiPlus, -kKPlus, +kPiPlus, -kPiPlus}, true, &sign, 3); - if (indexRecResoPartReco > -1) { - flag = sign * DecayTypeMc::Ds1ToDstarK0ToD0NoPiK0sPart; - } + } + } else if (std::abs(flagCharmBachInterm) > 0 && flagV0 == hf_decay::hf_cand_reso::PartialMatchMc::K0Matched) { + std::array pdgCodesDaughters = {+kPiPlus, -kKPlus, +kPiPlus, -kPiPlus}; + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[3], vecDaughtersReso[4]}; + // Peaking background of D0K0s <- Ds* with spurious soft pion + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDstarK0s) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::ResoPartlyMatched); + break; } } } - if (flag != 0) { - int indexParticle{-1}; - if (indexRecReso > -1) { - indexParticle = indexRecReso; - } else if (indexRecResoPartReco > -1) { - indexParticle = indexRecResoPartReco; - } - auto particleReso = particlesMc.iteratorAt(indexParticle); - origin = RecoDecay::getCharmHadronOrigin(particlesMc, particleReso, false, &idxBhadMothers); - motherPt = particleReso.pt(); + // No physical channel expected in D*Lambda + if (indexRec > -1) { + auto particleReso = particlesMc.iteratorAt(indexRec); + ptGen = particleReso.pt(); invMassGen = RecoDecay::m(particleReso.p(), particleReso.e()); } - if (doMcRecQa) { - if (indexRecReso > -1) { - if (nPiToMuReso == 0 && nKaToPiReso == 0) { - registry.fill(HIST("hMassVsPtDs1Matched"), varUtils.ptD, varUtils.invMassReso - varUtils.invMassD); - } - if (nPiToMuReso >= 1) { - registry.fill(HIST("hMassVsPtDs1MatchedPiToMu"), varUtils.ptD, varUtils.invMassReso - varUtils.invMassD); - } - if (nKaToPiReso >= 1) { - registry.fill(HIST("hMassVsPtDs1MatchedKaToPi"), varUtils.ptD, varUtils.invMassReso - varUtils.invMassD); + rowHfDstarV0McRecReduced(indexHfCandCharm, indexCandV0Bach, + flagReso, flagCharmBach, + flagCharmBachInterm, debugMcRec, + origin, ptGen, invMassGen, + nKinkedTracks); + } else if constexpr (dType == DType::Dplus) { + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong0Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong1Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong2Id())); + // Check if D+ is matched + flagCharmBach = candCharmBach.flagMcMatchRec(); + flagCharmBachInterm = candCharmBach.flagMcDecayChanRec(); + if (std::abs(flagCharmBach) > 0) { + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::DplusMatched); + origin = candCharmBach.originMcRec(); + } + // Check if V0 is matched + vecDaughtersReso.push_back(tracks.rawIteratorAt(bachelorV0.posTrackId())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(bachelorV0.negTrackId())); + flagV0 = getMatchingFlagV0(particlesMc, std::array{vecDaughtersReso[3], vecDaughtersReso[4]}); + if (std::abs(flagV0) > 0) { + SETBIT(debugMcRec, std::abs(flagV0)); + } + // If both D+ and K0s are matched, try to match resonance + if (hf_decay::hf_cand_3prong::daughtersDplusMain.contains(static_cast(std::abs(flagCharmBach))) && flagV0 == hf_decay::hf_cand_reso::PartialMatchMc::K0Matched) { + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], vecDaughtersReso[3], vecDaughtersReso[4]}; + auto pdgCodesDplusDaughters = hf_decay::hf_cand_3prong::daughtersDplusMain.at(static_cast(std::abs(flagCharmBach))); + auto pdgCodesDaughters = std::array{pdgCodesDplusDaughters[0], pdgCodesDplusDaughters[1], pdgCodesDplusDaughters[2], +kPiPlus, -kPiPlus}; + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDplusK0s) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + break; } } - if (indexRecD0 > -1) { - if (nPiToMuD0 == 0 && nKaToPiD0 == 0) { - registry.fill(HIST("hMassVsPtD0Matched"), varUtils.ptD, varUtils.invMassD0); - } - if (nPiToMuD0 >= 1) { - registry.fill(HIST("hMassVsPtD0MatchedPiToMu"), varUtils.ptD, varUtils.invMassD0); - } - if (nKaToPiD0 >= 1) { - registry.fill(HIST("hMassVsPtD0MatchedKaToPi"), varUtils.ptD, varUtils.invMassD0); + } else if (hf_decay::hf_cand_3prong::daughtersDplusMain.contains(static_cast(std::abs(flagCharmBach))) && std::abs(flagV0) == hf_decay::hf_cand_reso::PartialMatchMc::LambdaMatched) { + // Peaking background of D+Lambda <- Ds* with spurious soft pion + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], vecDaughtersReso[3], vecDaughtersReso[4]}; + auto pdgCodesDplusDaughters = hf_decay::hf_cand_3prong::daughtersDplusMain.at(static_cast(std::abs(flagCharmBach))); + auto pdgCodesDaughters = std::array{pdgCodesDplusDaughters[0], pdgCodesDplusDaughters[1], pdgCodesDplusDaughters[2], +kProton, -kPiPlus}; + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDplusLambda) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + break; } } - if (indexRecDstar > -1) { - if (nPiToMuDstar == 0 && nKaToPiDstar == 0) { - registry.fill(HIST("hMassVsPtDstarMatched"), varUtils.ptD, varUtils.invMassD - varUtils.invMassD0); - } - if (nPiToMuDstar >= 1) { - registry.fill(HIST("hMassVsPtDstarMatchedPiToMu"), varUtils.ptD, varUtils.invMassD - varUtils.invMassD0); - } - if (nKaToPiDstar >= 1) { - registry.fill(HIST("hMassVsPtDstarMatchedKaToPi"), varUtils.ptD, varUtils.invMassD - varUtils.invMassD0); + } + if (indexRec > -1) { + auto particleReso = particlesMc.iteratorAt(indexRec); + ptGen = particleReso.pt(); + invMassGen = RecoDecay::m(particleReso.p(), particleReso.e()); + } + rowHf3PrV0McRecReduced(indexHfCandCharm, indexCandV0Bach, + flagReso, flagCharmBach, + flagCharmBachInterm, debugMcRec, + origin, ptGen, invMassGen, + nKinkedTracks); + } else if constexpr (dType == DType::D0) { + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong0Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong1Id())); + // Check if D0 is matched + flagCharmBach = candCharmBach.flagMcMatchRec(); + flagCharmBachInterm = candCharmBach.flagMcDecayChanRec(); + if (std::abs(flagCharmBach) > 0) { + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::D0Matched); + origin = candCharmBach.originMcRec(); + } + // Check if V0 is matched + vecDaughtersReso.push_back(tracks.rawIteratorAt(bachelorV0.posTrackId())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(bachelorV0.negTrackId())); + flagV0 = getMatchingFlagV0(particlesMc, std::array{vecDaughtersReso[2], vecDaughtersReso[3]}); + if (std::abs(flagV0) > 0) { + SETBIT(debugMcRec, std::abs(flagV0)); + } + // No physical channel expected in D0 K0s + // If both D0 and Lambda are matched, try to match resonance + if (hf_decay::hf_cand_2prong::daughtersD0Main.contains(static_cast(std::abs(flagCharmBach))) && std::abs(flagV0) == hf_decay::hf_cand_reso::PartialMatchMc::LambdaMatched) { + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], vecDaughtersReso[3]}; + auto pdgCodesDzeroDaughters = hf_decay::hf_cand_2prong::daughtersD0Main.at(static_cast(std::abs(flagCharmBach))); + auto pdgCodesDaughters = std::array{pdgCodesDzeroDaughters[0], pdgCodesDzeroDaughters[1], +kProton, -kPiPlus}; + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToD0Lambda) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + break; } } - if (indexRecK0 > -1) { - if (nPiToMuV0 == 0 && nKaToPiV0 == 0) { - registry.fill(HIST("hMassVsPtK0Matched"), candidateV0.pT, candidateV0.mK0Short); - } - if (nPiToMuV0 >= 1) { - registry.fill(HIST("hMassVsPtK0MatchedPiToMu"), candidateV0.pT, candidateV0.mK0Short); - } - if (nKaToPiV0 >= 1) { - registry.fill(HIST("hMassVsPtK0MatchedKaToPi"), candidateV0.pT, candidateV0.mK0Short); + } + if (indexRec > -1) { + auto particleReso = particlesMc.iteratorAt(indexRec); + ptGen = particleReso.pt(); + invMassGen = RecoDecay::m(particleReso.p(), particleReso.e()); + } + rowHf2PrV0McRecReduced(indexHfCandCharm, indexCandV0Bach, + flagReso, flagCharmBach, + flagCharmBachInterm, debugMcRec, + origin, ptGen, invMassGen, + nKinkedTracks); + } + registry.fill(HIST("hMCRecDebug"), debugMcRec); + if (indexRec > -1) { + registry.fill(HIST("hMCRecCounter"), flagReso); + registry.fill(HIST("hMCRecOrigin"), origin); + registry.fill(HIST("hMCRecMassGen"), invMassGen); + } + if (std::abs(flagCharmBach) > 0) { + registry.fill(HIST("hMCRecCharmDau"), flagCharmBach); + } + } + + template + int8_t getMatchingFlagTrack(Tr const& bachTrack) + { + auto particle = bachTrack.mcParticle(); + auto pdgCode = std::abs(particle.pdgCode()); + if (pdgCode == kPiPlus) { + return hf_decay::hf_cand_reso::PartialMatchMc::PionMatched; + } else if (pdgCode == kKPlus) { + return hf_decay::hf_cand_reso::PartialMatchMc::KaonMatched; + } else if (pdgCode == kProton) { + return hf_decay::hf_cand_reso::PartialMatchMc::ProtonMatched; + } + return 0; + } + // Function for filling MC reco information of D Track candidates in the tables + /// \tparam dType is the D meson type (Dstar, Dplus or D0) + /// \param particlesMc is the table with MC particles + /// \param candCharmBach is the D meson candidate + /// \param bachelorTrack is the bachelor track + /// \param tracks is the table with tracks + /// \param indexHfCandCharm is the index of the charm-hadron bachelor in the reduced table + /// \param indexCandTrBach is the index of the v0 bachelor in the reduced table + template + void fillMcRecoInfoDTrack(PParticles const& particlesMc, + CCand const& candCharmBach, + BBachTr const& bachelorTrack, + Tr const& tracks, + int& indexHfCandCharm, + int64_t& indexCandTrBach) + { + std::vector vecDaughtersReso{}; + int8_t sign{0}, nKinkedTracks{0}, origin{0}, flagCharmBach{0}, flagCharmBachInterm{0}, flagTrack{0}, flagReso{0}; + int indexRec{-1}; + uint16_t debugMcRec{0}; + float ptGen{-1.f}, invMassGen{-1.f}; + if constexpr (dType == DType::Dstar) { + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong0Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong1Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prongPiId())); + // Check if D* is matched + flagCharmBach = candCharmBach.flagMcMatchRec(); + if (std::abs(flagCharmBach) > 0) { + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::DstarMatched); + origin = candCharmBach.originMcRec(); + } + // Check if D0 is matched + flagCharmBachInterm = candCharmBach.flagMcMatchRecD0(); + if (std::abs(flagCharmBachInterm) > 0) { + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::D0Matched); + } + // Check if Track is matched + flagTrack = getMatchingFlagTrack(bachelorTrack); + if (std::abs(flagTrack) > 0) { + SETBIT(debugMcRec, flagTrack); + } + // If both D* and Track are matched, try to match resonance + if (std::abs(flagCharmBach) > 0 && flagTrack == hf_decay::hf_cand_reso::PartialMatchMc::PionMatched) { + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], bachelorTrack}; + auto pdgCodesDaughters = std::array{+kPiPlus, -kKPlus, +kPiPlus, -kPiPlus}; + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDstarPi) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + break; } } } + // No channels in D*K+ or D*Pr + if (indexRec > -1) { + auto particleReso = particlesMc.iteratorAt(indexRec); + ptGen = particleReso.pt(); + invMassGen = RecoDecay::m(particleReso.p(), particleReso.e()); + } + rowHfDstarTrkMcRecReduced(indexHfCandCharm, indexCandTrBach, + flagReso, flagCharmBach, + flagCharmBachInterm, debugMcRec, + origin, ptGen, invMassGen, + nKinkedTracks); } else if constexpr (dType == DType::Dplus) { - // Ds2Star → D+ K0 → (π+K-π+) K0s → (π+K-π+)(π+π-) - indexRecK0 = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[3], vecDaughtersReso[4]}, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signV0, 2, &nPiToMuV0, &nKaToPiV0); - indexRecDplus = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2]}, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &signDplus, 2, &nPiToMuDplus, &nKaToPiDplus); - if (indexRecK0 > -1 && indexRecDplus > -1) { - indexRecReso = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], vecDaughtersReso[3], vecDaughtersReso[4]}, Pdg::kDS2Star, std::array{+kPiPlus, -kKPlus, +kPiPlus, +kPiPlus, -kPiPlus}, true, &sign, 3, &nPiToMuReso, &nKaToPiReso); - if (indexRecReso > -1 && nPiToMuReso == 0 && nKaToPiReso == 0) { - flag = sign * DecayTypeMc::Ds2StarToDplusK0sToPiKaPiPiPi; - } else if (indexRecReso > -1 && nPiToMuReso >= 1 && nKaToPiReso == 0) { - flag = sign * DecayTypeMc::Ds2StarToDplusK0sOneMu; - } else if (indexRecReso < 0) { - // Verify partly reconstructed decay Ds1 -> D* K0s -> D+ π0 K0s - indexRecDstar = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2]}, Pdg::kDStar, std::array{-kKPlus, +kPiPlus, +kPiPlus}, true, &signDstar, 2); - if (indexRecDstar > -1) { - indexRecReso = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], vecDaughtersReso[3], vecDaughtersReso[4]}, Pdg::kDS1, std::array{+kPiPlus, -kKPlus, +kPiPlus, +kPiPlus, -kPiPlus}, true, &sign, 3); - if (indexRecReso > -1) { - flag = sign * DecayTypeMc::Ds1ToDstarK0ToDplusPi0K0s; - } + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong0Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong1Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong2Id())); + // Check if D+ is matched + flagCharmBach = candCharmBach.flagMcMatchRec(); + flagCharmBachInterm = candCharmBach.flagMcDecayChanRec(); + if (std::abs(flagCharmBach) > 0) { + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::DplusMatched); + origin = candCharmBach.originMcRec(); + } + // Check if Track is matched + flagTrack = getMatchingFlagTrack(bachelorTrack); + if (std::abs(flagTrack) > 0) { + SETBIT(debugMcRec, flagTrack); + } + // If both D+ and Track are matched, try to match resonance + if (hf_decay::hf_cand_3prong::daughtersDplusMain.contains(static_cast(std::abs(flagCharmBach))) && flagTrack == hf_decay::hf_cand_reso::PartialMatchMc::PionMatched) { + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], bachelorTrack}; + auto pdgCodesDplusDaughters = hf_decay::hf_cand_3prong::daughtersDplusMain.at(static_cast(std::abs(flagCharmBach))); + auto pdgCodesDaughters = std::array{pdgCodesDplusDaughters[0], pdgCodesDplusDaughters[1], pdgCodesDplusDaughters[2], -kPiPlus}; + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDplusPi) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + break; } } } - if (flag != 0) { - auto particleReso = particlesMc.iteratorAt(indexRecReso); - origin = RecoDecay::getCharmHadronOrigin(particlesMc, particleReso, false, &idxBhadMothers); - motherPt = particleReso.pt(); + // No channels in D+K+ or D+Pr + if (indexRec > -1) { + auto particleReso = particlesMc.iteratorAt(indexRec); + ptGen = particleReso.pt(); invMassGen = RecoDecay::m(particleReso.p(), particleReso.e()); } - if (doMcRecQa) { - if (indexRecReso > -1) { - if (nPiToMuReso == 0 && nKaToPiReso == 0) { - registry.fill(HIST("hMassVsPtDs2StarMatched"), varUtils.ptD, varUtils.invMassReso - varUtils.invMassD); - } - if (nPiToMuReso >= 1) { - registry.fill(HIST("hMassVsPtDs2StarMatchedPiToMu"), varUtils.ptD, varUtils.invMassReso - varUtils.invMassD); - } - if (nKaToPiReso >= 1) { - registry.fill(HIST("hMassVsPtDs2StarMatchedKaToPi"), varUtils.ptD, varUtils.invMassReso - varUtils.invMassD); - } - } - if (indexRecDplus > -1) { - if (nPiToMuDplus == 0 && nKaToPiDplus == 0) { - registry.fill(HIST("hMassVsPtDplusMatched"), varUtils.ptD, varUtils.invMassD); - } - if (nPiToMuDplus >= 1) { - registry.fill(HIST("hMassVsPtDplusMatchedPiToMu"), varUtils.ptD, varUtils.invMassD); - } - if (nKaToPiDplus >= 1) { - registry.fill(HIST("hMassVsPtDplusMatchedKaToPi"), varUtils.ptD, varUtils.invMassD); + rowHf3PrTrkMcRecReduced(indexHfCandCharm, indexCandTrBach, + flagReso, flagCharmBach, + flagCharmBachInterm, debugMcRec, + origin, ptGen, invMassGen, + nKinkedTracks); + } else if constexpr (dType == DType::D0) { + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong0Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong1Id())); + // Check if D0 is matched + flagCharmBach = candCharmBach.flagMcMatchRec(); + flagCharmBachInterm = candCharmBach.flagMcDecayChanRec(); + if (std::abs(flagCharmBach) > 0) { + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::D0Matched); + origin = candCharmBach.originMcRec(); + } + if (hf_decay::hf_cand_2prong::daughtersD0Main.contains(static_cast(std::abs(flagCharmBach))) && flagTrack == hf_decay::hf_cand_reso::PartialMatchMc::PionMatched) { + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], bachelorTrack}; + auto pdgCodesDzeroDaughters = hf_decay::hf_cand_2prong::daughtersD0Main.at(static_cast(std::abs(flagCharmBach))); + auto pdgCodesDaughters = std::array{pdgCodesDzeroDaughters[0], pdgCodesDzeroDaughters[1], +kPiPlus}; + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToD0Pi) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + break; } } - if (indexRecK0 > -1) { - if (nPiToMuV0 == 0 && nKaToPiV0 == 0) { - registry.fill(HIST("hMassVsPtK0Matched"), candidateV0.pT, candidateV0.mK0Short); - } - if (nPiToMuV0 >= 1) { - registry.fill(HIST("hMassVsPtK0MatchedPiToMu"), candidateV0.pT, candidateV0.mK0Short); - } - if (nKaToPiV0 >= 1) { - registry.fill(HIST("hMassVsPtK0MatchedKaToPi"), candidateV0.pT, candidateV0.mK0Short); + } else if (hf_decay::hf_cand_2prong::daughtersD0Main.contains(static_cast(std::abs(flagCharmBach))) && flagTrack == hf_decay::hf_cand_reso::PartialMatchMc::KaonMatched) { + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], bachelorTrack}; + auto pdgCodesDzeroDaughters = hf_decay::hf_cand_2prong::daughtersD0Main.at(static_cast(std::abs(flagCharmBach))); + auto pdgCodesDaughters = std::array{pdgCodesDzeroDaughters[0], pdgCodesDzeroDaughters[1], +kKPlus}; + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToD0Kplus) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + break; } } } - } // DecayChannel::DplusV0 - if (flag != 0) { - registry.fill(HIST("hMCRecCounter"), flag); + if (indexRec > -1) { + auto particleReso = particlesMc.iteratorAt(indexRec); + ptGen = particleReso.pt(); + invMassGen = RecoDecay::m(particleReso.p(), particleReso.e()); + } + rowHf2PrTrkMcRecReduced(indexHfCandCharm, indexCandTrBach, + flagReso, flagCharmBach, + flagCharmBachInterm, debugMcRec, + origin, ptGen, invMassGen, + nKinkedTracks); + } + registry.fill(HIST("hMCRecDebug"), debugMcRec); + if (indexRec > -1) { + registry.fill(HIST("hMCRecCounter"), flagReso); registry.fill(HIST("hMCRecOrigin"), origin); registry.fill(HIST("hMCRecMassGen"), invMassGen); - } else { - if (indexRecK0 > -1) { - SETBIT(debug, PartialMatchMc::K0Matched); - } - if (indexRecD0 > -1) { - SETBIT(debug, PartialMatchMc::D0Matched); - } - if (indexRecDstar > -1) { - SETBIT(debug, PartialMatchMc::DstarMatched); - } - if (indexRecDplus > -1) { - SETBIT(debug, PartialMatchMc::DplusMatched); - } - registry.fill(HIST("hMCRecDebug"), debug); } - rowHfDV0McRecReduced(indexHfCandCharm, indexCandV0, flag, debug, origin, signD0, motherPt, invMassGen); - } + if (std::abs(flagCharmBach) > 0) { + registry.fill(HIST("hMCRecCharmDau"), flagCharmBach); + } + } // fillMcRecoInfoDTrack - template + template void runDataCreation(Coll const& collision, CCands const& candsD, BBachV0s const& bachelorV0s, BBachTracks const& bachelorTrks, Tr const& tracks, - TrIU const&, + TrIU const& tracksIU, PParticles const& particlesMc, - aod::BCsWithTimestamps const&) + BCs const&) { // helpers for ReducedTables filling + float centrality = -1.f; + uint16_t hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + if (rejectCollisionsWithBadEvSel && hfRejMap != 0) { + return; + } int indexHfReducedCollision = hfReducedCollision.lastIndex() + 1; // std::map where the key is the V0.globalIndex() and // the value is the V0 index in the table of the selected v0s @@ -850,7 +998,7 @@ struct HfDataCreatorCharmResoReduced { bool fillHfReducedCollision = false; constexpr bool DoTracks = pairingType == PairingType::TrackOnly || pairingType == PairingType::V0AndTrack; constexpr bool DoV0s = pairingType == PairingType::V0Only || pairingType == PairingType::V0AndTrack; - auto bc = collision.template bc_as(); + auto bc = collision.template bc_as(); if (runNumber != bc.runNumber()) { LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; initCCDB(bc, runNumber, ccdb, ccdbPathGrpMag, lut, false); @@ -864,7 +1012,6 @@ struct HfDataCreatorCharmResoReduced { bool fillHfCandD = false; std::array secondaryVertexD; std::array prongIdsD; - int8_t dtype{0}; std::array bdtScores = {-1.f, -1.f, -1.f, -1.f, -1.f, -1.f}; std::vector> charmHadDauTracks{}; varUtils.ptD = candD.pt(); @@ -886,16 +1033,14 @@ struct HfDataCreatorCharmResoReduced { varUtils.pVectorProng0 = candD.pVectorProng0(); varUtils.pVectorProng1 = candD.pVectorProng1(); varUtils.pVectorProng2 = candD.pVecSoftPi(); - charmHadDauTracks.push_back(candD.template prong0_as()); - charmHadDauTracks.push_back(candD.template prong1_as()); - charmHadDauTracks.push_back(candD.template prongPi_as()); - dtype = varUtils.signD * DType::Dstar; + charmHadDauTracks.push_back(tracksIU.rawIteratorAt(candD.prong0Id())); + charmHadDauTracks.push_back(tracksIU.rawIteratorAt(candD.prong1Id())); if constexpr (withMl) { std::copy(candD.mlProbDstarToD0Pi().begin(), candD.mlProbDstarToD0Pi().end(), bdtScores.begin()); } registry.fill(HIST("hMassVsPtDstarAll"), varUtils.ptD, varUtils.invMassD - varUtils.invMassD0); } else if constexpr (dType == DType::Dplus) { - auto prong0 = candD.template prong0_as(); + auto prong0 = tracksIU.rawIteratorAt(candD.prong0Id()); varUtils.invMassD = hfHelper.invMassDplusToPiKPi(candD); secondaryVertexD[0] = candD.xSecondaryVertex(); secondaryVertexD[1] = candD.ySecondaryVertex(); @@ -907,14 +1052,13 @@ struct HfDataCreatorCharmResoReduced { varUtils.pVectorProng0 = candD.pVectorProng0(); varUtils.pVectorProng1 = candD.pVectorProng1(); varUtils.pVectorProng2 = candD.pVectorProng2(); - dtype = static_cast(varUtils.signD * DType::Dplus); - charmHadDauTracks.push_back(candD.template prong0_as()); - charmHadDauTracks.push_back(candD.template prong1_as()); - charmHadDauTracks.push_back(candD.template prong2_as()); + charmHadDauTracks.push_back(tracksIU.rawIteratorAt(candD.prong0Id())); + charmHadDauTracks.push_back(tracksIU.rawIteratorAt(candD.prong1Id())); + charmHadDauTracks.push_back(tracksIU.rawIteratorAt(candD.prong2Id())); if constexpr (withMl) { std::copy(candD.mlProbDplusToPiKPi().begin(), candD.mlProbDplusToPiKPi().end(), bdtScores.begin()); } - registry.fill(HIST("hMassVsPtDplusAll"), varUtils.ptD, varUtils.invMassD0); + registry.fill(HIST("hMassVsPtDplusAll"), varUtils.ptD, varUtils.invMassD); } else if constexpr (dType == DType::D0) { varUtils.invMassD0 = hfHelper.invMassD0ToPiK(candD); varUtils.invMassD0Bar = hfHelper.invMassD0barToKPi(candD); @@ -924,8 +1068,8 @@ struct HfDataCreatorCharmResoReduced { prongIdsD[0] = candD.prong0Id(); prongIdsD[1] = candD.prong1Id(); prongIdsD[2] = -1; // D0 does not have a third prong - charmHadDauTracks.push_back(candD.template prong0_as()); - charmHadDauTracks.push_back(candD.template prong1_as()); + charmHadDauTracks.push_back(tracksIU.rawIteratorAt(candD.prong0Id())); + charmHadDauTracks.push_back(tracksIU.rawIteratorAt(candD.prong1Id())); varUtils.pVectorProng0 = candD.pVectorProng0(); varUtils.pVectorProng1 = candD.pVectorProng1(); varUtils.pVectorProng2 = {0.f, 0.f, 0.f}; // D0 does not have a third prong @@ -933,11 +1077,19 @@ struct HfDataCreatorCharmResoReduced { std::copy(candD.mlProbD0().begin(), candD.mlProbD0().end(), bdtScores.begin()); std::copy(candD.mlProbD0bar().begin(), candD.mlProbD0bar().end(), bdtScores.begin() + 3); } + if (candD.isSelD0() >= cfgDmesCuts.selectionFlagD0) { + registry.fill(HIST("hMassVsPtD0All"), varUtils.ptD, varUtils.invMassD0); + } + if (candD.isSelD0bar() >= cfgDmesCuts.selectionFlagD0Bar) { + registry.fill(HIST("hMassVsPtD0BarAll"), varUtils.ptD, varUtils.invMassD0Bar); + } } // end of dType switch // Get single track variables float chi2TpcDauMax = -1.f; int nItsClsDauMin = 8, nTpcCrossRowsDauMin = 200; + float chi2TpcSoftPi = -1.f; + int nItsClsSoftPi = 8, nTpcCrossRowsSoftPi = 200; for (const auto& charmHadTrack : charmHadDauTracks) { if (charmHadTrack.itsNCls() < nItsClsDauMin) { nItsClsDauMin = charmHadTrack.itsNCls(); @@ -949,12 +1101,18 @@ struct HfDataCreatorCharmResoReduced { chi2TpcDauMax = charmHadTrack.tpcChi2NCl(); } } - + if constexpr (dType == DType::Dstar) { + auto softPi = tracksIU.rawIteratorAt(candD.prongPiId()); + nItsClsSoftPi = softPi.itsNCls(); + nTpcCrossRowsSoftPi = softPi.tpcNClsCrossedRows(); + chi2TpcSoftPi = softPi.tpcChi2NCl(); + charmHadDauTracks.push_back(softPi); + } // Loop on the bachelor V0s if constexpr (DoV0s) { for (const auto& v0 : bachelorV0s) { - auto trackPos = v0.template posTrack_as(); - auto trackNeg = v0.template negTrack_as(); + auto trackPos = tracksIU.rawIteratorAt(v0.posTrackId()); + auto trackNeg = tracksIU.rawIteratorAt(v0.negTrackId()); // Apply selsection auto v0DauTracks = std::array{trackPos, trackNeg}; if (!buildAndSelectV0(collision, prongIdsD, v0DauTracks)) { @@ -985,7 +1143,7 @@ struct HfDataCreatorCharmResoReduced { getPxPyPz(trackParK0, candidateV0.mom); } // compute resonance invariant mass and filling of QA histograms - if (TESTBIT(candidateV0.v0Type, K0s)) { + if (TESTBIT(candidateV0.v0Type, BachelorType::K0s)) { registry.fill(HIST("hMassVsPtK0s"), candidateV0.pT, candidateV0.mK0Short); switch (dType) { case DType::Dstar: @@ -1018,8 +1176,8 @@ struct HfDataCreatorCharmResoReduced { break; // no other D meson types expected } // end of dType switch } // matched with K0s - bool isLambda = TESTBIT(candidateV0.v0Type, Lambda); - bool isAntiLambda = TESTBIT(candidateV0.v0Type, AntiLambda); + bool isLambda = TESTBIT(candidateV0.v0Type, BachelorType::Lambda); + bool isAntiLambda = TESTBIT(candidateV0.v0Type, BachelorType::AntiLambda); if (isLambda || isAntiLambda) { registry.fill(HIST("hMassVsPtLambda"), candidateV0.pT, candidateV0.mLambda); switch (dType) { @@ -1057,8 +1215,8 @@ struct HfDataCreatorCharmResoReduced { } varUtils.ptReso = RecoDecay::pt(RecoDecay::sumOfVec(varUtils.pVectorProng0, varUtils.pVectorProng1, candidateV0.mom)); if (!cfgQaPlots.applyCutsForQaHistograms || - (varUtils.invMassD0 > cfgQaPlots.cutMassDMin && - varUtils.invMassD0 < cfgQaPlots.cutMassDMax && + (((varUtils.invMassD0 > cfgQaPlots.cutMassDMin && varUtils.invMassD0 < cfgQaPlots.cutMassDMax) || + (varUtils.invMassD0Bar > cfgQaPlots.cutMassDMin && varUtils.invMassD0Bar < cfgQaPlots.cutMassDMax)) && candidateV0.mLambda > cfgQaPlots.cutMassLambdaMin && candidateV0.mLambda < cfgQaPlots.cutMassLambdaMax)) { if (isLambda) { @@ -1072,7 +1230,6 @@ struct HfDataCreatorCharmResoReduced { break; } // end of dType switch } // matched with Lambda or AntiLambda - // fill V0 table // if information on V0 already stored, go to next V0 if (!selectedV0s.count(v0.globalIndex())) { @@ -1089,16 +1246,15 @@ struct HfDataCreatorCharmResoReduced { } fillHfCandD = true; // Optional filling of MC Rec table, for now only implemented for Ds1->D*K0s and Ds2*->D+K0s - if constexpr (doMc && (dType == DType::Dstar || dType == DType::Dplus)) { - std::vector> charmResoDauTracks{}; - for (const auto& track : charmHadDauTracks) { - charmResoDauTracks.push_back(track); - } - charmResoDauTracks.push_back(trackPos); - charmResoDauTracks.push_back(trackNeg); - int indexHfCandCharm = hfCandD3Pr.lastIndex() + 1; - int indexHfCandV0 = hfCandV0.lastIndex(); - fillMcRecoInfo(particlesMc, charmResoDauTracks, indexHfCandCharm, indexHfCandV0); + if constexpr (doMc) { + int indexHfCandCharm{-1}; + if constexpr (dType == DType::Dstar) + indexHfCandCharm = hfCandDstar.lastIndex() + 1; + else if constexpr (dType == DType::Dplus) + indexHfCandCharm = hfCandD3Pr.lastIndex() + 1; + else if constexpr (dType == DType::D0) + indexHfCandCharm = hfCandD2Pr.lastIndex() + 1; + fillMcRecoInfoDV0(particlesMc, candD, v0, tracksIU, indexHfCandCharm, selectedV0s[v0.globalIndex()]); } } // end of loop on V0 candidates } // end of do V0s @@ -1288,18 +1444,28 @@ struct HfDataCreatorCharmResoReduced { selectedTracks[track.globalIndex()] = hfTrackNoParam.lastIndex(); } fillHfCandD = true; + if constexpr (doMc) { + int indexHfCandCharm{-1}; + if constexpr (dType == DType::Dstar) + indexHfCandCharm = hfCandDstar.lastIndex() + 1; + else if constexpr (dType == DType::Dplus) + indexHfCandCharm = hfCandD3Pr.lastIndex() + 1; + else if constexpr (dType == DType::D0) + indexHfCandCharm = hfCandD2Pr.lastIndex() + 1; + fillMcRecoInfoDTrack(particlesMc, candD, track, tracks, indexHfCandCharm, selectedTracks[track.globalIndex()]); + } } // end of loop on bachelor tracks } // end of do tracks // fill D candidate table if (fillHfCandD) { // fill candDplus table only once per D candidate, only if at least one V0 is found - if constexpr (dType == DType::Dstar || dType == DType::Dplus) { + if constexpr (dType == DType::Dplus) { hfCandD3Pr(prongIdsD[0], prongIdsD[1], prongIdsD[2], indexHfReducedCollision, secondaryVertexD[0], secondaryVertexD[1], secondaryVertexD[2], candD.pxProng0(), candD.pyProng0(), candD.pzProng0(), candD.pxProng1(), candD.pyProng1(), candD.pzProng1(), varUtils.pVectorProng2[0], varUtils.pVectorProng2[1], varUtils.pVectorProng2[2], - nItsClsDauMin, nTpcCrossRowsDauMin, chi2TpcDauMax, dtype); + nItsClsDauMin, nTpcCrossRowsDauMin, chi2TpcDauMax, varUtils.signD); if constexpr (withMl) { hfCandD3PrMl(bdtScores[0], bdtScores[1], bdtScores[2], bdtScores[3], bdtScores[4], bdtScores[5]); } @@ -1321,6 +1487,19 @@ struct HfDataCreatorCharmResoReduced { if constexpr (withMl) { hfCandD2PrMl(bdtScores[0], bdtScores[1], bdtScores[2], bdtScores[3], bdtScores[4], bdtScores[5]); } + } else if constexpr (dType == DType::Dstar) { + hfCandDstar(prongIdsD[0], prongIdsD[1], prongIdsD[2], + indexHfReducedCollision, + secondaryVertexD[0], secondaryVertexD[1], secondaryVertexD[2], + candD.pxProng0(), candD.pyProng0(), candD.pzProng0(), + candD.pxProng1(), candD.pyProng1(), candD.pzProng1(), + varUtils.pVectorProng2[0], varUtils.pVectorProng2[1], varUtils.pVectorProng2[2], + nItsClsDauMin, nTpcCrossRowsDauMin, chi2TpcDauMax, + nItsClsSoftPi, nTpcCrossRowsSoftPi, chi2TpcSoftPi, + varUtils.signD); + if constexpr (withMl) { + hfCandD3PrMl(bdtScores[0], bdtScores[1], bdtScores[2], bdtScores[3], bdtScores[4], bdtScores[5]); + } } fillHfReducedCollision = true; if constexpr (dType == DType::Dstar) { @@ -1328,10 +1507,13 @@ struct HfDataCreatorCharmResoReduced { } else if constexpr (dType == DType::Dplus) { registry.fill(HIST("hMassVsPtDplusPaired"), candD.pt(), varUtils.invMassD); } else if constexpr (dType == DType::D0) { - registry.fill(HIST("hMassVsPtD0Paired"), candD.pt(), varUtils.invMassD0); - registry.fill(HIST("hMassVsPtD0BarPaired"), candD.pt(), varUtils.invMassD0Bar); + if (candD.isSelD0() >= cfgDmesCuts.selectionFlagD0) { + registry.fill(HIST("hMassVsPtD0Paired"), varUtils.ptD, varUtils.invMassD0); + } + if (candD.isSelD0bar() >= cfgDmesCuts.selectionFlagD0Bar) { + registry.fill(HIST("hMassVsPtD0BarPaired"), varUtils.ptD, varUtils.invMassD0Bar); + } } - registry.fill(HIST("hDType"), dtype); } } // candsD loop registry.fill(HIST("hEvents"), 1 + Event::Processed); @@ -1340,144 +1522,179 @@ struct HfDataCreatorCharmResoReduced { return; } registry.fill(HIST("hEvents"), 1 + Event::DV0Selected); - float centrality = -1.f; - uint32_t hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); // fill collision table if it contains a DPi pair a minima hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), hfRejMap, bz); } // end of runDataCreation function - // to be modified in the future to allow for different decay channels - template - void runMcGen(aod::McParticles const& particlesMc) + template + void runMcGen(McParticles const& mcParticles, + CCs const& collInfos, + McCollisions const& mcCollisions, + BCsInfo const&) { - // Match generated particles. - for (const auto& particle : particlesMc) { - int8_t sign{0}; - int8_t flag{0}; - int8_t signDstar{0}; - int8_t signDplus{0}; - int8_t signV0{0}; - int8_t origin = 0; - std::vector idxBhadMothers{}; - - if constexpr (decayChannel == DecayChannel::DstarV0) { - // Ds1 → D* K0 - if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kDS1, std::array{static_cast(Pdg::kDStar), +kK0}, true, &sign, 1)) { - registry.fill(HIST("hMCSignCounter"), sign); - origin = RecoDecay::getCharmHadronOrigin(particlesMc, particle, false, &idxBhadMothers); - registry.fill(HIST("hMCGenOrigin"), origin); - auto candV0MC = particlesMc.rawIteratorAt(particle.daughtersIds().back()); - auto candDstarMC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); - // K0 -> K0s -> π+π- - if (RecoDecay::isMatchedMCGen(particlesMc, candV0MC, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signV0, 2)) { - // D* -> D0 π+ -> K-π+π+ - if (RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kD0), +static_cast(kPiPlus)}, true, &signDstar, 1)) { - auto candD0MC = particlesMc.rawIteratorAt(candDstarMC.daughtersIds().front()); - if (RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{-kKPlus, +kPiPlus, +kPiPlus}, true, &signDstar, 2)) { - flag = signDstar * DecayTypeMc::Ds1ToDstarK0ToD0PiK0s; - } else if (RecoDecay::isMatchedMCGen(particlesMc, candD0MC, Pdg::kD0, std::array{-kKPlus, +kPiPlus, +kPiPlus, +kPi0}, true, &signDstar, 2) || - RecoDecay::isMatchedMCGen(particlesMc, candD0MC, Pdg::kD0, std::array{-kKPlus, +kPiPlus, +kPiPlus, -kPi0}, true, &signDstar, 2)) { - flag = signDstar * DecayTypeMc::Ds1ToDstarK0ToD0PiK0sPart; + bool doV0s = (pairingType == PairingType::V0Only || pairingType == PairingType::V0AndTrack); + bool doTracks = (pairingType == PairingType::TrackOnly || pairingType == PairingType::V0AndTrack); + for (const auto& mcCollision : mcCollisions) { + // Slice the particles table to get the particles for the current MC collision + const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); + // Slice the collisions table to get the collision info for the current MC collision + float centrality{-1.f}; + uint16_t rejectionMask{0}; + int nSplitColl = 0; + const auto collSlice = collInfos.sliceBy(colPerMcCollision, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + hfEvSelMc.fillHistograms(mcCollision, rejectionMask, nSplitColl); + if (rejectCollisionsWithBadEvSel && rejectionMask != 0) { + // at least one event selection not satisfied --> reject all gen particles from this collision + continue; + } + for (const auto& particle : mcParticlesPerMcColl) { + int8_t sign{0}; + int8_t flag{0}; + int8_t signD{0}; + int8_t signBach{0}; + int8_t origin{0}; + bool matchedReso{false}, matchedD{false}, matchedV0Tr{false}; + std::vector idxBhadMothers{}; + if constexpr (dType == DType::Dstar) { + if (doV0s) { + // D* K0s + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDstarK0s) { + matchedReso = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, particle, pdgCodeReso, std::array{static_cast(Pdg::kDStar), +kK0}, true, &sign, 1); + if (matchedReso) { + flag = sign * decayChannelFlag; + auto candV0MC = mcParticles.rawIteratorAt(particle.daughtersIds().back()); + matchedV0Tr = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, candV0MC, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signBach, 2); + break; } - } else if (RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), static_cast(kGamma)}, true, &signDstar, 1) || - RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), -static_cast(kGamma)}, true, &signDstar, 1) || - RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), static_cast(kPi0)}, true, &signDstar, 1) || - RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), -static_cast(kPi0)}, true, &signDstar, 1)) { - auto candDplusMC = particlesMc.rawIteratorAt(candDstarMC.daughtersIds().front()); - if (RecoDecay::isMatchedMCGen(particlesMc, candDplusMC, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &signDplus, 2)) - flag = sign * DecayTypeMc::Ds1ToDstarK0ToDplusPi0K0s; } } - } else { - if (std::abs(particle.pdgCode()) == Pdg::kDS1) { - origin = RecoDecay::getCharmHadronOrigin(particlesMc, particle, false, &idxBhadMothers); - registry.fill(HIST("hMCOriginCounterWrongDecay"), origin); + if (doTracks && !matchedReso) { + // D*+ pi- + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDstarPi) { + matchedReso = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, particle, pdgCodeReso, std::array{static_cast(Pdg::kDStar), -static_cast(kPiPlus)}, true, &sign, 1); + if (matchedReso) { + flag = sign * decayChannelFlag; + matchedV0Tr = true; + break; + } + } } - } - // save information for task - if (flag == 0) { - continue; - } - - auto ptParticle = particle.pt(); - auto yParticle = RecoDecay::y(particle.pVector(), MassDS1); - auto etaParticle = particle.eta(); - - std::array ptProngs; - std::array yProngs; - std::array etaProngs; - int counter = 0; - for (const auto& daught : particle.daughters_as()) { - ptProngs[counter] = daught.pt(); - etaProngs[counter] = daught.eta(); - yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); - counter++; - } - registry.fill(HIST("hMCGenCounter"), flag, ptParticle); - rowHfResoMcGenReduced(flag, origin, ptParticle, yParticle, etaParticle, - ptProngs[0], yProngs[0], etaProngs[0], - ptProngs[1], yProngs[1], etaProngs[1]); - } else if constexpr (decayChannel == DecayChannel::DplusV0) { // Ds2Star → D+ K0 - if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kDS2Star, std::array{static_cast(Pdg::kDPlus), +kK0}, true, &sign, 1)) { - registry.fill(HIST("hMCSignCounter"), sign); - origin = RecoDecay::getCharmHadronOrigin(particlesMc, particle, false, &idxBhadMothers); - registry.fill(HIST("hMCGenOrigin"), origin); - auto candV0MC = particlesMc.rawIteratorAt(particle.daughtersIds().back()); - auto candDplusMC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); - // K0 -> K0s -> π+π- - if (RecoDecay::isMatchedMCGen(particlesMc, candV0MC, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signV0, 2)) { - // D* -> D0 π+ -> K-π+π+ - if (RecoDecay::isMatchedMCGen(particlesMc, candDplusMC, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &signDplus, 2)) { - flag = sign * DecayTypeMc::Ds2StarToDplusK0sToPiKaPiPiPi; + if (matchedReso && matchedV0Tr) { + auto candDstarMC = mcParticles.rawIteratorAt(particle.daughtersIds().front()); + matchedD = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kD0), +static_cast(kPiPlus)}, true, &signD, 1); + if (matchedD) { + auto candD0MC = mcParticles.rawIteratorAt(candDstarMC.daughtersIds().front()); + matchedD = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, candD0MC, Pdg::kD0, std::array{-kKPlus, +kPiPlus}, true, &signD, 2); } } - } else if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kDS1, std::array{static_cast(Pdg::kDStar), +kK0}, true, &sign, 1)) { - auto candV0MC = particlesMc.rawIteratorAt(particle.daughtersIds().back()); - // K0 -> K0s -> π+π- - if (RecoDecay::isMatchedMCGen(particlesMc, candV0MC, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signV0, 2)) { - auto candDstarMC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); - // D* -> D+ π0/γ ->π+K-π+ π0/γ - if (RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), static_cast(kGamma)}, true, &signDstar, 1) || - RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), -static_cast(kGamma)}, true, &signDstar, 1) || - RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), static_cast(kPi0)}, true, &signDstar, 1) || - RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), -static_cast(kPi0)}, true, &signDstar, 1)) { - auto candDplusMC = particlesMc.rawIteratorAt(candDstarMC.daughtersIds().front()); - if (RecoDecay::isMatchedMCGen(particlesMc, candDplusMC, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &signDplus, 2)) - flag = sign * DecayTypeMc::Ds1ToDstarK0ToDplusPi0K0s; + } else if constexpr (dType == DType::Dplus) { + if (doV0s) { + // D+ K0s + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDplusK0s) { + matchedReso = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, particle, pdgCodeReso, std::array{static_cast(Pdg::kDPlus), +kK0}, true, &sign, 1); + if (matchedReso) { + flag = sign * decayChannelFlag; + auto candV0MC = mcParticles.rawIteratorAt(particle.daughtersIds().back()); + matchedV0Tr = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, candV0MC, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signBach, 2); + break; + } + } + if (!matchedReso) { + // D+ lambda + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDplusLambda) { + matchedReso = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, particle, pdgCodeReso, std::array{static_cast(Pdg::kDPlus), +kLambda0}, true, &sign, 1); + if (matchedReso) { + flag = sign * decayChannelFlag; + auto candV0MC = mcParticles.rawIteratorAt(particle.daughtersIds().back()); + matchedV0Tr = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, candV0MC, kLambda0, std::array{+kProton, -kPiPlus}, true, &signBach, 1); + break; + } + } } } - } else { - if (std::abs(particle.pdgCode()) == Pdg::kDS2Star) { - origin = RecoDecay::getCharmHadronOrigin(particlesMc, particle, false, &idxBhadMothers); - registry.fill(HIST("hMCOriginCounterWrongDecay"), origin); + if (doTracks && !matchedReso) { + // D+ pi- + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDplusPi) { + matchedReso = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, particle, pdgCodeReso, std::array{static_cast(Pdg::kDPlus), -static_cast(kPiPlus)}, true, &sign, 1); + if (matchedReso) { + flag = sign * decayChannelFlag; + matchedV0Tr = true; + break; + } + } + } + if (matchedReso && matchedV0Tr) { + auto candDplusMC = mcParticles.rawIteratorAt(particle.daughtersIds().front()); + matchedD = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, candDplusMC, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &signD, 2); + } + } else if constexpr (dType == DType::D0) { + if (doV0s) { + // D0 Lambda + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToD0Lambda) { + matchedReso = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, particle, pdgCodeReso, std::array{static_cast(Pdg::kD0), +kLambda0}, true, &sign, 1); + if (matchedReso) { + flag = sign * decayChannelFlag; + auto candV0MC = mcParticles.rawIteratorAt(particle.daughtersIds().back()); + matchedV0Tr = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, candV0MC, kLambda0, std::array{+kProton, -kPiPlus}, true, &signBach, 1); + break; + } + } + } + if (doTracks && !matchedReso) { + // D0 pi+ + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToD0Pi) { + matchedReso = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, particle, pdgCodeReso, std::array{static_cast(Pdg::kD0), +static_cast(kPiPlus)}, true, &sign, 1); + if (matchedReso) { + flag = sign * decayChannelFlag; + matchedV0Tr = true; + break; + } + } + // D0 K+ + if (!matchedReso) { + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToD0Kplus) { + matchedReso = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, particle, pdgCodeReso, std::array{static_cast(Pdg::kD0), +static_cast(kKPlus)}, true, &sign, 1); + if (matchedReso) { + flag = sign * decayChannelFlag; + matchedV0Tr = true; + break; + } + } + } + } + if (matchedReso && matchedV0Tr) { + auto candD0MC = mcParticles.rawIteratorAt(particle.daughtersIds().front()); + matchedD = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, candD0MC, Pdg::kD0, std::array{-kKPlus, +kPiPlus}, true, &signD, 2); } } - // save information for task - if (flag == 0) { - continue; - } - - auto ptParticle = particle.pt(); - auto yParticle = RecoDecay::y(particle.pVector(), MassDS2Star); - auto etaParticle = particle.eta(); - - std::array ptProngs; - std::array yProngs; - std::array etaProngs; - int counter = 0; - for (const auto& daught : particle.daughters_as()) { - ptProngs[counter] = daught.pt(); - etaProngs[counter] = daught.eta(); - yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); - counter++; + if (matchedReso && matchedD && matchedV0Tr) { + origin = RecoDecay::getCharmHadronOrigin(mcParticlesPerMcColl, particle, false, &idxBhadMothers); + registry.fill(HIST("hMCGenOrigin"), origin); + auto ptParticle = particle.pt(); + auto invMassGen = RecoDecay::m(particle.p(), particle.e()); + auto yParticle = RecoDecay::y(particle.pVector(), invMassGen); + auto etaParticle = particle.eta(); + + std::array ptProngs; + std::array yProngs; + std::array etaProngs; + int counter = 0; + for (const auto& daught : particle.template daughters_as()) { + ptProngs[counter] = daught.pt(); + etaProngs[counter] = daught.eta(); + yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); + counter++; + } + registry.fill(HIST("hMCGenCounter"), flag, ptParticle); + rowHfResoMcGenReduced(flag, origin, ptParticle, yParticle, etaParticle, + ptProngs[0], yProngs[0], etaProngs[0], + ptProngs[1], yProngs[1], etaProngs[1], + invMassGen, rejectionMask); } - registry.fill(HIST("hMCGenCounter"), flag, ptParticle); - rowHfResoMcGenReduced(flag, origin, ptParticle, yParticle, etaParticle, - ptProngs[0], yProngs[0], etaProngs[0], - ptProngs[1], yProngs[1], etaProngs[1]); - } // Dplus V0 - } // for loop - } // gen + } + } + } // Process functions // No ML @@ -1704,61 +1921,6 @@ struct HfDataCreatorCharmResoReduced { } PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processD0V0AndTrack, "Process D0 candidates paired with V0s and Tracks", false); - // MC - // D* - void processDstarV0MC(soa::Join const& collisions, - CandsDstarFiltered const& candsDstar, - aod::V0s const& v0s, - TracksIUWithPIDAndMC const& tracksIU, - aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs) - { - int zvtxColl{0}; - int sel8Coll{0}; - int zvtxAndSel8Coll{0}; - int zvtxAndSel8CollAndSoftTrig{0}; - int allSelColl{0}; - for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); - auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); - auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, bcs); - } - runMcGen(particlesMc); - // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - } - PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0MC, "Process Dstar candidates paired with V0s with MC matching", false); - - // Dplus - void processDplusV0MC(soa::Join const& collisions, - CandsDplusFiltered const& candsDplus, - aod::V0s const& v0s, - TracksIUWithPIDAndMC const& tracksIU, - aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs) - { - int zvtxColl{0}; - int sel8Coll{0}; - int zvtxAndSel8Coll{0}; - int zvtxAndSel8CollAndSoftTrig{0}; - int allSelColl{0}; - for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); - auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); - auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, bcs); - } - runMcGen(particlesMc); - // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - } - PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0MC, "Process Dstar candidates paired with V0s with MC matching", false); - // D0 - // Not implemented yet - // ML // Data // D* @@ -1984,13 +2146,271 @@ struct HfDataCreatorCharmResoReduced { PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processD0V0AndTrackWithMl, "Process D0 candidates paired with V0s and Tracks with ML info", false); // MC + // No ML + // D* + void processDstarV0MC(soa::Join const& collisions, + CandsDstarFilteredWithMc const& candsDstar, + aod::V0s const& v0s, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, v0sThisColl, tracksIU, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0MC, "Process Dstar candidates paired with V0s with MC matching", false); + + void processDstarTrackMC(soa::Join const& collisions, + CandsDstarFilteredWithMc const& candsDstar, + TracksWithPIDAndMC const& tracks, + aod::TrackAssoc const& trackIndices, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarTrackMC, "Process Dstar candidates paired with tracks with MC matching", false); + + void processDstarV0AndTrackMC(soa::Join const& collisions, + CandsDstarFilteredWithMc const& candsDstar, + aod::V0s const& v0s, + aod::TrackAssoc const& trackIndices, + TracksWithPIDAndMC const& tracks, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0AndTrackMC, "Process Dstar candidates paired with V0s and tracks with MC matching", false); + + // Dplus + void processDplusV0MC(soa::Join const& collisions, + CandsDplusFilteredWithMc const& candsDplus, + aod::V0s const& v0s, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, v0sThisColl, tracksIU, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0MC, "Process Dstar candidates paired with V0s with MC matching", false); + + void processDplusTrackMC(soa::Join const& collisions, + CandsDplusFilteredWithMc const& candsDplus, + TracksWithPIDAndMC const& tracks, + aod::TrackAssoc const& trackIndices, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusTrackMC, "Process Dplus candidates paired with tracks with MC matching", false); + + void processDplusV0AndTrackMC(soa::Join const& collisions, + CandsDplusFilteredWithMc const& candsDplus, + aod::V0s const& v0s, + aod::TrackAssoc const& trackIndices, + TracksWithPIDAndMC const& tracks, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0AndTrackMC, "Process Dplus candidates paired with V0s and tracks with MC matching", false); + + // D0 + void processD0V0MC(soa::Join const& collisions, + CandsD0FilteredWithMc const& candsD0, + aod::V0s const& v0s, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, v0sThisColl, tracksIU, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processD0V0MC, "Process D0 candidates paired with V0s with MC matching", false); + + void processD0TrackMC(soa::Join const& collisions, + CandsD0FilteredWithMc const& candsD0, + TracksWithPIDAndMC const& tracks, + aod::TrackAssoc const& trackIndices, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processD0TrackMC, "Process D0 candidates paired with tracks with MC matching", false); + + void processD0V0AndTrackMC(soa::Join const& collisions, + CandsD0FilteredWithMc const& candsD0, + aod::V0s const& v0s, + aod::TrackAssoc const& trackIndices, + TracksWithPIDAndMC const& tracks, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processD0V0AndTrackMC, "Process D0 candidates paired with V0s and tracks with MC matching", false); + // ML // D* void processDstarV0MCWithMl(soa::Join const& collisions, - CandsDstarFilteredWithMl const& candsDstar, + CandsDstarFilteredWithMlAndMc const& candsDstar, aod::V0s const& v0s, TracksIUWithPIDAndMC const& tracksIU, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs) + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) { int zvtxColl{0}; int sel8Coll{0}; @@ -1998,25 +2418,84 @@ struct HfDataCreatorCharmResoReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); + auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, bcs); } - runMcGen(particlesMc); + runMcGen(particlesMc, collInfos, mcCollisions, bcs); // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0MCWithMl, "Process Dstar candidates paired with V0s with MC matching and with ML info", false); + void processDstarTrackMCWithMl(soa::Join const& collisions, + CandsDstarFilteredWithMlAndMc const& candsDstar, + TracksWithPIDAndMC const& tracks, + aod::TrackAssoc const& trackIndices, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarTrackMCWithMl, "Process Dstar candidates paired with tracks with MC matching and with ML info", false); + + void processDstarV0AndTrackMCWithMl(soa::Join const& collisions, + CandsDstarFilteredWithMlAndMc const& candsDstar, + aod::V0s const& v0s, + aod::TrackAssoc const& trackIndices, + TracksWithPIDAndMC const& tracks, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0AndTrackMCWithMl, "Process Dstar candidates paired with V0s and tracks with MC matching and with ML info", false); + // Dplus void processDplusV0MCWithMl(soa::Join const& collisions, - CandsDplusFilteredWithMl const& candsDplus, + CandsDplusFilteredWithMlAndMc const& candsDplus, aod::V0s const& v0s, TracksIUWithPIDAndMC const& tracksIU, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs) + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) { int zvtxColl{0}; int sel8Coll{0}; @@ -2024,19 +2503,159 @@ struct HfDataCreatorCharmResoReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); + auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, bcs); } - runMcGen(particlesMc); + runMcGen(particlesMc, collInfos, mcCollisions, bcs); // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0MCWithMl, "Process Dplus candidates paired with V0s with MC matching and with ML info", false); + + void processDplusTrackMCWithMl(soa::Join const& collisions, + CandsDplusFilteredWithMlAndMc const& candsDplus, + TracksWithPIDAndMC const& tracks, + aod::TrackAssoc const& trackIndices, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusTrackMCWithMl, "Process Dplus candidates paired with tracks with MC matching and with ML info", false); + + void processDplusV0AndTrackMCWithMl(soa::Join const& collisions, + CandsDplusFilteredWithMlAndMc const& candsDplus, + aod::V0s const& v0s, + aod::TrackAssoc const& trackIndices, + TracksWithPIDAndMC const& tracks, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0AndTrackMCWithMl, "Process Dplus candidates paired with V0s and tracks with MC matching and with ML info", false); + // D0 - // Not implemented yet + void processD0V0MCWithMl(soa::Join const& collisions, + CandsD0FilteredWithMlAndMc const& candsD0, + aod::V0s const& v0s, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processD0V0MCWithMl, "Process D0 candidates paired with V0s with MC matching and with ML info", false); + + void processD0TrackMCWithMl(soa::Join const& collisions, + CandsD0FilteredWithMlAndMc const& candsD0, + TracksWithPIDAndMC const& tracks, + aod::TrackAssoc const& trackIndices, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processD0TrackMCWithMl, "Process D0 candidates paired with tracks with MC matching and with ML info", false); + + void processD0V0AndTrackMCWithMl(soa::Join const& collisions, + CandsD0FilteredWithMlAndMc const& candsD0, + aod::V0s const& v0s, + aod::TrackAssoc const& trackIndices, + TracksWithPIDAndMC const& tracks, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processD0V0AndTrackMCWithMl, "Process D0 candidates paired with V0s and tracks with MC matching and with ML info", false); }; // struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/D2H/Tasks/CMakeLists.txt b/PWGHF/D2H/Tasks/CMakeLists.txt index 3e1d565d1ea..24707fb011b 100644 --- a/PWGHF/D2H/Tasks/CMakeLists.txt +++ b/PWGHF/D2H/Tasks/CMakeLists.txt @@ -54,8 +54,13 @@ o2physics_add_dpl_workflow(task-charm-polarisation PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(task-charm-reso-reduced - SOURCES taskCharmResoReduced.cxx +o2physics_add_dpl_workflow(task-charm-reso-to-d-v0-reduced + SOURCES taskCharmResoToDV0Reduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(task-charm-reso-to-d-trk-reduced + SOURCES taskCharmResoToDTrkReduced.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGHF/D2H/Tasks/taskCharmResoReduced.cxx b/PWGHF/D2H/Tasks/taskCharmResoToDTrkReduced.cxx similarity index 50% rename from PWGHF/D2H/Tasks/taskCharmResoReduced.cxx rename to PWGHF/D2H/Tasks/taskCharmResoToDTrkReduced.cxx index feb872262b3..362933d9124 100644 --- a/PWGHF/D2H/Tasks/taskCharmResoReduced.cxx +++ b/PWGHF/D2H/Tasks/taskCharmResoToDTrkReduced.cxx @@ -9,12 +9,14 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file taskCharmResoReduced.cxx -/// \brief Charmed Resonances analysis task +/// \file taskCharmResoToDTrkReduced.cxx +/// \brief Charmed Resonances decaying in a D meson and a Track analysis task /// /// \author Luca Aglietta , University and INFN Torino +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/Utils/utilsMcMatching.h" #include "Common/Core/RecoDecay.h" @@ -38,19 +40,15 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::constants::physics; -enum DecayTypeMc : uint8_t { - Ds1ToDStarK0ToD0PiK0s = 1, - Ds2StarToDplusK0sToPiKaPiPiPi, - Ds1ToDStarK0ToDPlusPi0K0s, - Ds1ToDStarK0ToD0PiK0sPart, - Ds1ToDStarK0ToD0NoPiK0sPart, - Ds1ToDStarK0ToD0PiK0sOneMu, - Ds2StarToDplusK0sOneMu +enum BachelorType : uint8_t { + K0s = 0, + Lambda, + AntiLambda }; namespace o2::aod { -namespace hf_cand_reso_lite +namespace hf_cand_reso_to_trk_lite { DECLARE_SOA_COLUMN(PtBach0, ptBach0, float); //! Transverse momentum of bachelor 0 (GeV/c) DECLARE_SOA_COLUMN(PtBach1, ptBach1, float); //! Transverse momentum of bachelor 1 (GeV/c) @@ -72,72 +70,74 @@ DECLARE_SOA_COLUMN(MlScoreNonPromptBach0, mlScoreNonPromptBach0, float); DECLARE_SOA_COLUMN(ItsNClsProngMinBach0, itsNClsProngMinBach0, int); //! minimum value of number of ITS clusters for the decay daughter tracks of bachelor 0 DECLARE_SOA_COLUMN(TpcNClsCrossedRowsProngMinBach0, tpcNClsCrossedRowsProngMinBach0, int); //! minimum value of number of TPC crossed rows for the decay daughter tracks of bachelor 0 DECLARE_SOA_COLUMN(TpcChi2NClProngMaxBach0, tpcChi2NClProngMaxBach0, float); //! maximum value of TPC chi2 for the decay daughter tracks of bachelor 0 -DECLARE_SOA_COLUMN(ItsNClsProngMinBach1, itsNClsProngMinBach1, int); //! minimum value of number of ITS clusters for the decay daughter tracks of bachelor 1 -DECLARE_SOA_COLUMN(TpcNClsCrossedRowsProngMinBach1, tpcNClsCrossedRowsProngMinBach1, int); //! minimum value of number of TPC crossed rows for the decay daughter tracks of bachelor 1 -DECLARE_SOA_COLUMN(TpcChi2NClProngMaxBach1, tpcChi2NClProngMaxBach1, float); //! maximum value of TPC chi2 for the decay daughter tracks of bachelor 1 -DECLARE_SOA_COLUMN(CpaBach1, cpaBach1, float); //! Cosine of Pointing Angle of bachelor 1 -DECLARE_SOA_COLUMN(DcaBach1, dcaBach1, float); //! DCA of bachelor 1 -DECLARE_SOA_COLUMN(RadiusBach1, radiusBach1, float); //! Radius of bachelor 1 -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! flag for decay channel classification reconstruction level -DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); //! debug flag for mis-association at reconstruction level +DECLARE_SOA_COLUMN(ItsNClsBach1, itsNClsBach1, int); //! minimum value of number of ITS clusters for the decay daughter tracks of bachelor 1 +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsBach1, tpcNClsCrossedRowsBach1, int); //! minimum value of number of TPC crossed rows for the decay daughter tracks of bachelor 1 +DECLARE_SOA_COLUMN(TpcChi2NClBach1, tpcChi2NClBach1, float); //! maximum value of TPC chi2 for the decay daughter tracks of bachelor 1 +DECLARE_SOA_COLUMN(TpcNSigmaBach1, tpcNSigmaBach1, float); //! NsigmaTPC for Bach1 for its mass hypothesis +DECLARE_SOA_COLUMN(TofNSigmaBach1, tofNSigmaBach1, float); //! NsigmaTOF for Bach1 for its mass hypothesis +DECLARE_SOA_COLUMN(TpcTofNSigmaBach1, tpcTofNSigmaBach1, float); //! Combined NsigmaTPC-TOF for Bach1 for its mass hypothesis +DECLARE_SOA_COLUMN(FlagMcMatch, flagMcMatch, int8_t); //! flag for decay channel classification reconstruction level +DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int); //! debug flag for mis-association at reconstruction level DECLARE_SOA_COLUMN(Origin, origin, int8_t); //! Flag for origin of MC particle 1=promt, 2=FD DECLARE_SOA_COLUMN(PtGen, ptGen, float); //! Transverse momentum of candidate (GeV/c) -DECLARE_SOA_COLUMN(SignD0, signD0, float); //! Flag to distinguish D0 and D0Bar +DECLARE_SOA_COLUMN(InvMassGen, invMassGen, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(FlagCharmBach, flagCharmBach, int8_t); //! Flag for charm bachelor classification +DECLARE_SOA_COLUMN(FlagCharmBachInterm, flagCharmBachInterm, int8_t); //! Flag for charm bachelor classification intermediate +} // namespace hf_cand_reso_to_trk_lite -} // namespace hf_cand_reso_lite - -DECLARE_SOA_TABLE(HfCandResoLites, "AOD", "HFCANDRESOLITE", //! Table with some B0 properties +DECLARE_SOA_TABLE(HfCandDTrkLites, "AOD", "HFCANDDTRKLITE", //! Table with some B0 properties // Candidate Properties - hf_cand_reso_lite::M, - hf_cand_reso_lite::Pt, - hf_cand_reso_lite::P, - hf_cand_reso_lite::Y, - hf_cand_reso_lite::Eta, - hf_cand_reso_lite::Phi, - hf_cand_reso_lite::E, - hf_cand_reso_lite::CosThetaStar, - hf_cand_reso_lite::Sign, + hf_cand_reso_to_trk_lite::M, + hf_cand_reso_to_trk_lite::Pt, + hf_cand_reso_to_trk_lite::P, + hf_cand_reso_to_trk_lite::Y, + hf_cand_reso_to_trk_lite::Eta, + hf_cand_reso_to_trk_lite::Phi, + hf_cand_reso_to_trk_lite::E, + hf_cand_reso_to_trk_lite::CosThetaStar, + hf_cand_reso_to_trk_lite::Sign, // Bachelors Properties - hf_cand_reso_lite::MBach0, - hf_cand_reso_lite::PtBach0, - hf_cand_reso_lite::MlScoreBkgBach0, - hf_cand_reso_lite::MlScorePromptBach0, - hf_cand_reso_lite::MlScoreNonPromptBach0, - hf_cand_reso_lite::ItsNClsProngMinBach0, - hf_cand_reso_lite::TpcNClsCrossedRowsProngMinBach0, - hf_cand_reso_lite::TpcChi2NClProngMaxBach0, - hf_cand_reso_lite::MBach1, - hf_cand_reso_lite::PtBach1, - hf_cand_reso_lite::CpaBach1, - hf_cand_reso_lite::DcaBach1, - hf_cand_reso_lite::RadiusBach1, - hf_cand_reso_lite::ItsNClsProngMinBach1, - hf_cand_reso_lite::TpcNClsCrossedRowsProngMinBach1, - hf_cand_reso_lite::TpcChi2NClProngMaxBach1, + hf_cand_reso_to_trk_lite::MBach0, + hf_cand_reso_to_trk_lite::PtBach0, + hf_cand_reso_to_trk_lite::MlScoreBkgBach0, + hf_cand_reso_to_trk_lite::MlScorePromptBach0, + hf_cand_reso_to_trk_lite::MlScoreNonPromptBach0, + hf_cand_reso_to_trk_lite::ItsNClsProngMinBach0, + hf_cand_reso_to_trk_lite::TpcNClsCrossedRowsProngMinBach0, + hf_cand_reso_to_trk_lite::TpcChi2NClProngMaxBach0, + hf_cand_reso_to_trk_lite::PtBach1, + hf_cand_reso_to_trk_lite::ItsNClsBach1, + hf_cand_reso_to_trk_lite::TpcNClsCrossedRowsBach1, + hf_cand_reso_to_trk_lite::TpcChi2NClBach1, + hf_cand_reso_to_trk_lite::TpcNSigmaBach1, + hf_cand_reso_to_trk_lite::TofNSigmaBach1, + hf_cand_reso_to_trk_lite::TpcTofNSigmaBach1, // MC - hf_cand_reso_lite::FlagMcMatchRec, - hf_cand_reso_lite::DebugMcRec, - hf_cand_reso_lite::Origin, - hf_cand_reso_lite::PtGen, - hf_cand_reso_lite::SignD0); + hf_cand_reso_to_trk_lite::FlagMcMatch, + hf_cand_reso_to_trk_lite::DebugMcRec, + hf_cand_reso_to_trk_lite::Origin, + hf_cand_reso_to_trk_lite::PtGen, + hf_cand_reso_to_trk_lite::InvMassGen, + hf_cand_reso_to_trk_lite::FlagCharmBach, + hf_cand_reso_to_trk_lite::FlagCharmBachInterm); DECLARE_SOA_TABLE(HfGenResoLites, "AOD", "HFGENRESOLITE", //! Table with some B0 properties - hf_cand_reso_lite::Pt, - hf_cand_reso_lite::Y, - hf_cand_reso_lite::Origin); + hf_cand_reso_to_trk_lite::Pt, + hf_cand_reso_to_trk_lite::Y, + hf_cand_reso_to_trk_lite::Origin, + hf_cand_reso_to_trk_lite::FlagMcMatch); } // namespace o2::aod enum DecayChannel : uint8_t { - Ds1ToDstarK0s = 0, - Ds2StarToDplusK0s, - XcToDplusLambda, - LambdaDminus + D0Kplus = 0 }; -struct HfTaskCharmResoReduced { - Produces hfCandResoLite; +struct HfTaskCharmResoToDTrkReduced { + Produces hfCandResoLite; Produces hfGenResoLite; + + Configurable doWrongSign{"doWrongSign", false, "Flag to enable wrong sign candidates"}; Configurable ptMinReso{"ptMinReso", -1, "Discard events with smaller pT"}; Configurable fillTrees{"fillTrees", true, "Fill output Trees"}; Configurable fillSparses{"fillSparses", false, "Fill output Sparses"}; @@ -147,15 +147,18 @@ struct HfTaskCharmResoReduced { Configurable yCandRecoMax{"yCandRecoMax", -1, "max. cand. rapidity"}; Configurable etaTrackMax{"etaTrackMax", 0.8, "max. track pseudo-rapidity for acceptance calculation"}; Configurable ptTrackMin{"ptTrackMin", 0.1, "min. track transverse momentum for acceptance calculation"}; - Configurable massResoMin{"massResoMin", 0.49, "min. mass of resonance"}; + Configurable massResoMin{"massResoMin", 0.2, "min. mass of resonance"}; Configurable massResoMax{"massResoMax", 1.29, "max. mass of resonance"}; + + using ReducedReso2PrTrk = soa::Join; + using ReducedReso2PrTrkMC = soa::Join; + // Configurables axis for histos ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "#it{p}_{T} (GeV/#it{c})"}; ConfigurableAxis axisPtProng0{"axisPtProng0", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "prong0 bach. #it{p}_{T} (GeV/#it{c})"}; ConfigurableAxis axisPtProng1{"axisPtProng1", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "prong1 bach. #it{p}_{T} (GeV/#it{c})"}; ConfigurableAxis axisInvMassReso{"axisInvMassReso", {200, 2.34, 2.74}, "inv. mass (DV_{0}) (GeV/#it{c}^{2})"}; ConfigurableAxis axisInvMassProng0{"axisInvMassProng0", {175, 1.70, 2.05}, "inv. mass (D) (GeV/#it{c}^{2})"}; - ConfigurableAxis axisInvMassProng1{"axisInvMassProng1", {80, 0.46, 0.54}, "inv. mass ({V}_{0}) (GeV/#it{c}^{2})"}; ConfigurableAxis axisCosThetaStar{"axisCosThetaStar", {40, -1, 1}, "cos(#vartheta*)"}; ConfigurableAxis axisBkgBdtScore{"axisBkgBdtScore", {100, 0, 1}, "bkg BDT Score"}; ConfigurableAxis axisNonPromptBdtScore{"axisNonPromptBdtScore", {100, 0, 1}, "non-prompt BDT Score"}; @@ -163,36 +166,31 @@ struct HfTaskCharmResoReduced { ConfigurableAxis axisOrigin{"axisOrigin", {3, -0.5, 2.5}, "origin"}; ConfigurableAxis axisFlag{"axisFlag", {65, -32.5, 32.5}, "mc flag"}; - using ReducedReso = soa::Join; - using ReducedResoWithMl = soa::Join; - using ReducedResoMc = soa::Join; - using ReducedResoWithMlMc = soa::Join; - // Histogram Registry HistogramRegistry registry; // init void init(InitContext&) { - registry.add("hMass", "Charm resonance candidates inv. mass", {HistType::kTH1F, {axisInvMassReso}}); - registry.add("hMassProng0", "D daughters inv. mass", {HistType::kTH1F, {axisInvMassProng0}}); - registry.add("hMassProng1", "V0 daughter inv. mass", {HistType::kTH1F, {axisInvMassProng1}}); - registry.add("hPt", "Charm resonance candidates pT", {HistType::kTH1F, {axisPt}}); - registry.add("hPtProng0", "D daughters pT", {HistType::kTH1F, {axisPtProng0}}); - registry.add("hPtProng1", "V0 daughter pT", {HistType::kTH1F, {axisPtProng1}}); - registry.add("hNPvCont", "Collision number of PV contributors ; N contrib ; entries", {HistType::kTH1F, {{125, -0.5, 249.5}}}); - registry.add("hZvert", "Collision Z Vtx ; z PV [cm] ; entries", {HistType::kTH1F, {{120, -12., 12.}}}); - registry.add("hBz", "Collision Bz ; Bz [T] ; entries", {HistType::kTH1F, {{20, -10., 10.}}}); - registry.add("hSparse", "THn for production studies with cosThStar and BDT scores", HistType::kTHnSparseF, {axisPt, axisPtProng0, axisPtProng1, axisInvMassReso, axisInvMassProng0, axisInvMassProng1, axisCosThetaStar, axisBkgBdtScore, axisNonPromptBdtScore}); - - if (doprocessDs1Mc || doprocessDs2StarMc || doprocessDs1McWithMl || doprocessDs2StarMcWithMl) { + registry.add("hMass", "Charm resonance candidates inv. mass", {HistType::kTH1D, {axisInvMassReso}}); + registry.add("hMassProng0", "D daughters inv. mass", {HistType::kTH1D, {axisInvMassProng0}}); + registry.add("hPt", "Charm resonance candidates pT", {HistType::kTH1D, {axisPt}}); + registry.add("hPtProng0", "D daughters pT", {HistType::kTH1D, {axisPtProng0}}); + registry.add("hPtProng1", "Track daughter pT", {HistType::kTH1D, {axisPtProng1}}); + registry.add("hNPvCont", "Collision number of PV contributors ; N contrib ; entries", {HistType::kTH1D, {{125, -0.5, 249.5}}}); + registry.add("hZvert", "Collision Z Vtx ; z PV [cm] ; entries", {HistType::kTH1D, {{120, -12., 12.}}}); + registry.add("hBz", "Collision Bz ; Bz [T] ; entries", {HistType::kTH1D, {{20, -10., 10.}}}); + registry.add("hSparse", "THn for production studies with cosThStar and BDT scores", HistType::kTHnSparseF, {axisPt, axisPtProng0, axisPtProng1, axisInvMassReso, axisInvMassProng0, axisCosThetaStar, axisBkgBdtScore, axisNonPromptBdtScore}); + + if (doprocessD0KplusMC || doprocessD0KplusMCWithMl) { // gen histos - registry.add("hYRecPrompt", "Charm resonance candidates pT", {HistType::kTH2F, {axisPt, axisEta}}); - registry.add("hYRecNonPrompt", "Charm resonance candidates pT", {HistType::kTH2F, {axisPt, axisEta}}); - registry.add("hYGenPrompt", "Prompt {D_{S}}^j particles (generated);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2F, {axisPt, axisEta}}); - registry.add("hYGenPromptWithProngsInAcceptance", "Prompt {D_{S}}^j particles (generated-daughters in acceptance);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2F, {axisPt, axisEta}}); - registry.add("hYGenNonPrompt", "NonPrompt {D_{S}}^j particles (generated);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2F, {axisPt, axisEta}}); - registry.add("hYGenNonPromptWithProngsInAcceptance", "NonPrompt {D_{S}}^j particles (generated-daughters in acceptance);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2F, {axisPt, axisEta}}); + registry.add("hYRecPrompt", "Charm resonance candidates pT", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYRecNonPrompt", "Charm resonance candidates pT", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenAll", "Prompt {D_{S}}^j particles (generated);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenPrompt", "Prompt {D_{S}}^j particles (generated);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenPromptWithProngsInAcceptance", "Prompt {D_{S}}^j particles (generated-daughters in acceptance);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenNonPrompt", "NonPrompt {D_{S}}^j particles (generated);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenNonPromptWithProngsInAcceptance", "NonPrompt {D_{S}}^j particles (generated-daughters in acceptance);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); if (fillSparses) { registry.add("hPtYGenSig", "{D_{S}}^j particles (generated);#it{p}_{T}({D_{S}}^j) (GeV/#it{c});#it{y}({D_{S}}^j)", {HistType::kTHnSparseF, {axisPt, axisEta, axisOrigin, axisFlag}}); registry.add("hPtYWithProngsInAccepanceGenSig", "{D_{S}}^j particles (generated-daughters in acceptance);#it{p}_{T}({D_{S}}^j) (GeV/#it{c});#it{y}({D_{S}}^j)", {HistType::kTHnSparseF, {axisPt, axisEta, axisOrigin, axisFlag}}); @@ -206,108 +204,95 @@ struct HfTaskCharmResoReduced { /// \param coll is a reduced collision /// \param bach0 is a bachelor of the candidate /// \param bach1 is a bachelor of the candidate - template - void fillCand(const Cand& candidate, const Coll& collision, const CharmBach& bach0, const V0Bach& bach1) + template + void fillCand(const Cand& candidate, const Coll& collision, const CharmBach& bach0, const TrkBach& bach1) { - // Compute quantities to be saved - float invMassReso{0}, pdgMassReso, invMassBach0, invMassBach1, pdgMassBach0, pdgMassBach1, sign, invMassD0, cosThetaStar; - if (channel == DecayChannel::Ds1ToDstarK0s) { - pdgMassReso = MassDS1; - pdgMassBach0 = MassDStar; - pdgMassBach1 = MassK0; - invMassBach1 = bach1.invMassK0s(); - cosThetaStar = candidate.cosThetaStarDs1(); - if (bach0.dType() > 0) { - invMassBach0 = bach0.invMassDstar(); - invMassD0 = bach0.invMassD0(); - sign = 1; - if (useDeltaMass) { - invMassReso = RecoDecay::m(std::array{bach0.pVectorProng0(), bach0.pVectorProng1(), bach0.pVectorProng2(), bach1.pVector()}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0}); - } - } else { - invMassBach0 = bach0.invMassAntiDstar(); - invMassD0 = bach0.invMassD0Bar(); - sign = -1; - if (useDeltaMass) { - invMassReso = RecoDecay::m(std::array{bach0.pVectorProng1(), bach0.pVectorProng0(), bach0.pVectorProng2(), bach1.pVector()}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0}); - } - } - } else if (channel == DecayChannel::Ds2StarToDplusK0s) { - pdgMassReso = MassDS2Star; - pdgMassBach0 = MassDPlus; - pdgMassBach1 = MassK0; - invMassBach0 = bach0.invMassDplus(); - invMassD0 = 0; - invMassBach1 = bach1.invMassK0s(); - cosThetaStar = candidate.cosThetaStarDs2Star(); - if (useDeltaMass) { - invMassReso = RecoDecay::m(std::array{bach0.pVectorProng0(), bach0.pVectorProng1(), bach0.pVectorProng2(), bach1.pVector()}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0}); - } - if (bach0.dType() > 0) { - sign = 1; - } else { - sign = -1; - } + // Base + float massReso{0}, cosThetaStar{0}; + int8_t sign{0}; + float tpcNSigmaBach1{0}, tofNSigmaBach1{0}, tpcTofNSigmaBach1{0}; + if constexpr (channel == DecayChannel::D0Kplus) { + massReso = useDeltaMass ? candidate.invMass() + MassD0 : candidate.invMass(); + cosThetaStar = RecoDecay::cosThetaStar(std::array{bach0.pVector(), bach1.pVector()}, std::array{MassD0, MassKPlus}, massReso, 0); + tpcNSigmaBach1 = bach1.tpcNSigmaKa(); + tofNSigmaBach1 = bach1.tofNSigmaKa(); + tpcTofNSigmaBach1 = bach1.tpcTofNSigmaKa(); + sign = bach1.sign(); } - float y = RecoDecay::y(std::array{candidate.px(), candidate.py(), candidate.pz()}, pdgMassReso); + float y = RecoDecay::y(std::array{candidate.px(), candidate.py(), candidate.pz()}, massReso); float eta = RecoDecay::eta(std::array{candidate.px(), candidate.py(), candidate.pz()}); float phi = RecoDecay::phi(candidate.px(), candidate.py()); float p = RecoDecay::p(std::array{candidate.px(), candidate.py(), candidate.pz()}); - float e = RecoDecay::e(std::array{candidate.px(), candidate.py(), candidate.pz()}, pdgMassReso); - if (useDeltaMass) { - invMassReso = invMassReso - invMassBach0; - } else { - invMassReso = RecoDecay::m(std::array{bach0.pVector(), bach1.pVector()}, std::array{pdgMassBach0, pdgMassBach1}); - } - if (invMassReso < massResoMin || invMassReso > massResoMax) { - return; - } - invMassBach0 = invMassBach0 - invMassD0; - float ptGen{-1.}; - int8_t origin{-1}, flagMcMatchRec{-1}, debugMcRec{-1}, signD0{0}; + float e = RecoDecay::e(std::array{candidate.px(), candidate.py(), candidate.pz()}, massReso); + + // MC Rec + float ptGen{-1.}, invMassGen{-1}; + int8_t origin{0}, flagMcMatchRec{0}, flagCharmBach{0}, flagCharmBachInterm{0}; + int debugMcRec{-1}; if constexpr (doMc) { - ptGen = candidate.ptMother(); + ptGen = candidate.ptGen(); origin = candidate.origin(); flagMcMatchRec = candidate.flagMcMatchRec(); debugMcRec = candidate.debugMcRec(); + invMassGen = candidate.invMassGen(); + flagCharmBach = candidate.flagMcMatchRecD(); + flagCharmBachInterm = candidate.flagMcMatchChanD(); if (fillOnlySignal) { - if (channel == DecayChannel::Ds1ToDstarK0s && !(std::abs(flagMcMatchRec) == DecayTypeMc::Ds1ToDStarK0ToD0PiK0s || std::abs(flagMcMatchRec) == DecayTypeMc::Ds1ToDStarK0ToD0PiK0sPart || std::abs(flagMcMatchRec) == DecayTypeMc::Ds1ToDStarK0ToD0NoPiK0sPart || std::abs(flagMcMatchRec) == DecayTypeMc::Ds1ToDStarK0ToD0PiK0sOneMu)) { - return; - } - if (channel == DecayChannel::Ds2StarToDplusK0s && !(std::abs(flagMcMatchRec) == DecayTypeMc::Ds2StarToDplusK0sToPiKaPiPiPi || std::abs(flagMcMatchRec) == DecayTypeMc::Ds2StarToDplusK0sOneMu)) { + if (channel == DecayChannel::D0Kplus && + !hf_decay::hf_cand_reso::particlesToD0Kplus.contains(static_cast(std::abs(flagMcMatchRec)))) { return; } } - if (origin == 1) { + if (origin == RecoDecay::OriginType::Prompt) { registry.fill(HIST("hYRecPrompt"), candidate.pt(), y); - } else if (origin == 2) { + } else if (origin == RecoDecay::OriginType::NonPrompt) { registry.fill(HIST("hYRecNonPrompt"), candidate.pt(), y); } } + + // Ml float mlScoreBkg{-1.}, mlScorePrompt{-1.}, mlScoreNonPrompt{-1.}; if constexpr (withMl) { - mlScoreBkg = bach0.mlScoreBkgMassHypo0(); - mlScorePrompt = bach0.mlScorePromptMassHypo0(); - mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo0(); + if constexpr (channel == DecayChannel::D0Kplus) { + if (bach1.sign() > 0 && !doWrongSign) { + mlScoreBkg = bach0.mlScoreBkgMassHypo0(); + mlScorePrompt = bach0.mlScorePromptMassHypo0(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo0(); + } else if (bach1.sign() < 0 && !doWrongSign) { + mlScoreBkg = bach0.mlScoreBkgMassHypo1(); + mlScorePrompt = bach0.mlScorePromptMassHypo1(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo1(); + } else if (bach1.sign() > 0 && doWrongSign) { + mlScoreBkg = bach0.mlScoreBkgMassHypo1(); + mlScorePrompt = bach0.mlScorePromptMassHypo1(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo1(); + } else if (bach1.sign() < 0 && doWrongSign) { + mlScoreBkg = bach0.mlScoreBkgMassHypo0(); + mlScorePrompt = bach0.mlScorePromptMassHypo0(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo0(); + } + } else { + mlScoreBkg = bach0.mlScoreBkgMassHypo0(); + mlScorePrompt = bach0.mlScorePromptMassHypo0(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo0(); + } } // Collision properties registry.fill(HIST("hNPvCont"), collision.numContrib()); registry.fill(HIST("hZvert"), collision.posZ()); registry.fill(HIST("hBz"), collision.bz()); // Candidate properties - registry.fill(HIST("hMass"), invMassReso); - registry.fill(HIST("hMassProng0"), invMassBach0); - registry.fill(HIST("hMassProng1"), invMassBach1); + registry.fill(HIST("hMass"), candidate.invMass()); + registry.fill(HIST("hMassProng0"), candidate.invMassProng0()); registry.fill(HIST("hPt"), candidate.pt()); registry.fill(HIST("hPtProng0"), candidate.ptProng0()); registry.fill(HIST("hPtProng1"), candidate.ptProng1()); if (fillSparses) { - registry.fill(HIST("hSparse"), candidate.pt(), candidate.ptProng0(), candidate.ptProng1(), invMassReso, invMassBach0, invMassBach1, cosThetaStar, mlScoreBkg, mlScoreNonPrompt); + registry.fill(HIST("hSparse"), candidate.pt(), candidate.ptProng0(), candidate.ptProng1(), candidate.invMass(), candidate.invMassProng0(), cosThetaStar, mlScoreBkg, mlScoreNonPrompt); } - if (fillTrees) { hfCandResoLite( - invMassReso, + candidate.invMass(), candidate.pt(), p, y, @@ -317,7 +302,7 @@ struct HfTaskCharmResoReduced { cosThetaStar, sign, // Bachelors Properties - invMassBach0, + candidate.invMassProng0(), bach0.pt(), mlScoreBkg, mlScorePrompt, @@ -325,20 +310,21 @@ struct HfTaskCharmResoReduced { bach0.itsNClsProngMin(), bach0.tpcNClsCrossedRowsProngMin(), bach0.tpcChi2NClProngMax(), - invMassBach1, bach1.pt(), - bach1.cpa(), - bach1.dca(), - bach1.v0Radius(), - bach1.itsNClsProngMin(), - bach1.tpcNClsCrossedRowsProngMin(), - bach1.tpcChi2NClProngMax(), + bach1.itsNCls(), + bach1.tpcNClsCrossedRows(), + bach1.tpcChi2NCl(), + tpcNSigmaBach1, + tofNSigmaBach1, + tpcTofNSigmaBach1, // MC flagMcMatchRec, debugMcRec, origin, ptGen, - signD0); + invMassGen, + flagCharmBach, + flagCharmBachInterm); } } // fillCand @@ -346,27 +332,43 @@ struct HfTaskCharmResoReduced { /// \tparam channel is the decay channel of the Resonance /// \param Coll is the reduced collisions table /// \param CharmBach is the reduced 3 prong table - /// \param V0Bach is the reduced v0 table + /// \param TrkBach is the reduced v0 table /// \param Cand is the candidates table template - void processData(Coll const&, Candidates const& candidates, CharmBach const&, aod::HfRedVzeros const&) + void processData(Coll const&, Candidates const& candidates, CharmBach const&, aod::HfRedTrkNoParams const&) { for (const auto& cand : candidates) { if (ptMinReso >= 0 && cand.pt() < ptMinReso) { continue; } - float pdgMassReso{0}; - if (channel == DecayChannel::Ds1ToDstarK0s) { - pdgMassReso = MassDS1; - } else if (channel == DecayChannel::Ds2StarToDplusK0s) { - pdgMassReso = MassDS2Star; + if ((massResoMin >= 0 && cand.invMass() < massResoMin) || + (massResoMax >= 0 && cand.invMass() > massResoMax)) { + continue; } - if (yCandRecoMax >= 0. && std::abs(RecoDecay::y(std::array{cand.px(), cand.py(), cand.pz()}, pdgMassReso)) > yCandRecoMax) { + if (doWrongSign && cand.isWrongSign() == 0) { + continue; + } else if (!doWrongSign && cand.isWrongSign() != 0) { + continue; + } + + float massReso{0}; + if (useDeltaMass) { + switch (channel) { + case DecayChannel::D0Kplus: + massReso = cand.invMass() + MassD0; + break; + default: + break; + } + } else { + massReso = cand.invMass(); + } + if (yCandRecoMax >= 0. && std::abs(RecoDecay::y(std::array{cand.px(), cand.py(), cand.pz()}, massReso)) > yCandRecoMax) { continue; } auto coll = cand.template hfRedCollision_as(); auto bach0 = cand.template prong0_as(); - auto bach1 = cand.template prong1_as(); + auto bach1 = cand.template prong1_as(); fillCand(cand, coll, bach0, bach1); } } @@ -390,24 +392,26 @@ struct HfTaskCharmResoReduced { auto yParticle = particle.yTrack(); auto originParticle = particle.origin(); auto flag = particle.flagMcMatchGen(); - if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { - continue; - } std::array ptProngs = {particle.ptProng0(), particle.ptProng1()}; std::array etaProngs = {particle.etaProng0(), particle.etaProng1()}; bool prongsInAcc = isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1]); - if ((channel == DecayChannel::Ds1ToDstarK0s && std::abs(flag) == DecayTypeMc::Ds1ToDStarK0ToD0PiK0s) || - (channel == DecayChannel::Ds2StarToDplusK0s && std::abs(flag) == DecayTypeMc::Ds2StarToDplusK0sToPiKaPiPiPi)) { - if (originParticle == 1) { // prompt particles - registry.fill(HIST("hYGenPrompt"), ptParticle, yParticle); - if (prongsInAcc) { - registry.fill(HIST("hYGenPromptWithProngsInAcceptance"), ptParticle, yParticle); - } - } else if (originParticle == 2) { - registry.fill(HIST("hYGenNonPrompt"), ptParticle, yParticle); - if (prongsInAcc) { - registry.fill(HIST("hYGenNonPromptWithProngsInAcceptance"), ptParticle, yParticle); - } + if (channel == DecayChannel::D0Kplus && + !hf_decay::hf_cand_reso::particlesToD0Kplus.contains(static_cast(std::abs(flag)))) { + continue; + } + registry.fill(HIST("hYGenAll"), ptParticle, yParticle); + if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { + continue; + } + if (originParticle == RecoDecay::OriginType::Prompt) { // prompt particles + registry.fill(HIST("hYGenPrompt"), ptParticle, yParticle); + if (prongsInAcc) { + registry.fill(HIST("hYGenPromptWithProngsInAcceptance"), ptParticle, yParticle); + } + } else if (originParticle == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("hYGenNonPrompt"), ptParticle, yParticle); + if (prongsInAcc) { + registry.fill(HIST("hYGenNonPromptWithProngsInAcceptance"), ptParticle, yParticle); } } if (fillSparses) { @@ -417,67 +421,57 @@ struct HfTaskCharmResoReduced { } } if (fillTrees) { - hfGenResoLite(ptParticle, yParticle, originParticle); + hfGenResoLite(ptParticle, yParticle, originParticle, flag); } } } // fillCandMcGen // process functions - - void processDs1Data(aod::HfRedCollisions const& collisions, ReducedReso const& candidates, aod::HfRed3PrNoTrks const& charmBachs, aod::HfRedVzeros const& v0Bachs) + void processD0KplusData(aod::HfRedCollisions const& collisions, + ReducedReso2PrTrk const& candidates, + aod::HfRed2PrNoTrks const& charmBachs, + aod::HfRedTrkNoParams const& trkBachs) { - processData(collisions, candidates, charmBachs, v0Bachs); + processData(collisions, candidates, charmBachs, trkBachs); } - PROCESS_SWITCH(HfTaskCharmResoReduced, processDs1Data, "Process data for Ds1 analysis without Ml", true); + PROCESS_SWITCH(HfTaskCharmResoToDTrkReduced, processD0KplusData, "Process data for D0Kplus analysis", true); - void processDs1DataWithMl(aod::HfRedCollisions const& collisions, ReducedResoWithMl const& candidates, soa::Join const& charmBachs, aod::HfRedVzeros const& v0Bachs) + // Process data with ML + void processD0KplusDataWithMl(aod::HfRedCollisions const& collisions, + ReducedReso2PrTrk const& candidates, + soa::Join const& charmBachs, + aod::HfRedTrkNoParams const& trkBachs) { - processData(collisions, candidates, charmBachs, v0Bachs); + processData(collisions, candidates, charmBachs, trkBachs); } - PROCESS_SWITCH(HfTaskCharmResoReduced, processDs1DataWithMl, "Process data for Ds1 analysis with Ml", false); - - void processDs2StarData(aod::HfRedCollisions const& collisions, ReducedReso const& candidates, aod::HfRed3PrNoTrks const& charmBachs, aod::HfRedVzeros const& v0Bachs) - { - processData(collisions, candidates, charmBachs, v0Bachs); - } - PROCESS_SWITCH(HfTaskCharmResoReduced, processDs2StarData, "Process data Ds2Star analysis without Ml", false); - - void processDs2StarDataWithMl(aod::HfRedCollisions const& collisions, ReducedResoWithMl const& candidates, soa::Join const& charmBachs, aod::HfRedVzeros const& v0Bachs) - { - processData(collisions, candidates, charmBachs, v0Bachs); - } - PROCESS_SWITCH(HfTaskCharmResoReduced, processDs2StarDataWithMl, "Process data Ds2Star analysis with Ml", false); - - void processDs1Mc(aod::HfRedCollisions const& collisions, ReducedResoMc const& candidates, aod::HfMcGenRedResos const& mcParticles, aod::HfRed3PrNoTrks const& charmBachs, aod::HfRedVzeros const& v0Bachs) + PROCESS_SWITCH(HfTaskCharmResoToDTrkReduced, processD0KplusDataWithMl, "Process data for D0Kplus analysis with Ml", false); + + // MC + void processD0KplusMC(aod::HfRedCollisions const& collisions, + ReducedReso2PrTrkMC const& candidates, + aod::HfRed2PrNoTrks const& charmBachs, + aod::HfRedTrkNoParams const& trkBachs, + aod::HfMcGenRedResos const& mcParticles) { - processData(collisions, candidates, charmBachs, v0Bachs); - fillCandMcGen(mcParticles); + processData(collisions, candidates, charmBachs, trkBachs); + fillCandMcGen(mcParticles); } - PROCESS_SWITCH(HfTaskCharmResoReduced, processDs1Mc, "Process Mc for Ds1 analysis without Ml", false); - - void processDs1McWithMl(aod::HfRedCollisions const& collisions, ReducedResoWithMlMc const& candidates, aod::HfMcGenRedResos const& mcParticles, soa::Join const& charmBachs, aod::HfRedVzeros const& v0Bachs) - { - processData(collisions, candidates, charmBachs, v0Bachs); - fillCandMcGen(mcParticles); - } - PROCESS_SWITCH(HfTaskCharmResoReduced, processDs1McWithMl, "Process Mc for Ds1 analysis with Ml", false); - - void processDs2StarMc(aod::HfRedCollisions const& collisions, ReducedResoMc const& candidates, aod::HfMcGenRedResos const& mcParticles, aod::HfRed3PrNoTrks const& charmBachs, aod::HfRedVzeros const& v0Bachs) - { - processData(collisions, candidates, charmBachs, v0Bachs); - fillCandMcGen(mcParticles); - } - PROCESS_SWITCH(HfTaskCharmResoReduced, processDs2StarMc, "Process Mc for Ds2Star analysis without Ml", false); - - void processDs2StarMcWithMl(aod::HfRedCollisions const& collisions, ReducedResoWithMlMc const& candidates, aod::HfMcGenRedResos const& mcParticles, soa::Join const& charmBachs, aod::HfRedVzeros const& v0Bachs) + PROCESS_SWITCH(HfTaskCharmResoToDTrkReduced, processD0KplusMC, "Process MC for D0Kplus analysis", false); + + // MC with Ml + void processD0KplusMCWithMl(aod::HfRedCollisions const& collisions, + ReducedReso2PrTrkMC const& candidates, + soa::Join const& charmBachs, + aod::HfRedTrkNoParams const& trkBachs, + aod::HfMcGenRedResos const& mcParticles) { - processData(collisions, candidates, charmBachs, v0Bachs); - fillCandMcGen(mcParticles); + processData(collisions, candidates, charmBachs, trkBachs); + fillCandMcGen(mcParticles); } - PROCESS_SWITCH(HfTaskCharmResoReduced, processDs2StarMcWithMl, "Process Mc for Ds2Star analysis with Ml", false); + PROCESS_SWITCH(HfTaskCharmResoToDTrkReduced, processD0KplusMCWithMl, "Process MC for D0Kplus analysis with Ml", false); -}; // struct HfTaskCharmResoReduced +}; // struct HfTaskCharmResoToDTrkReduced WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGHF/D2H/Tasks/taskCharmResoToDV0Reduced.cxx b/PWGHF/D2H/Tasks/taskCharmResoToDV0Reduced.cxx new file mode 100644 index 00000000000..360b8a3002f --- /dev/null +++ b/PWGHF/D2H/Tasks/taskCharmResoToDV0Reduced.cxx @@ -0,0 +1,658 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file taskCharmResoToDV0Reduced.cxx +/// \brief Charmed Resonances decaying in a D meson and a V0 analysis task +/// +/// \author Luca Aglietta , University and INFN Torino + +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/Utils/utilsMcMatching.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace o2; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; + +enum BachelorType : uint8_t { + K0s = 0, + Lambda, + AntiLambda +}; + +namespace o2::aod +{ +namespace hf_cand_reso_to_v0_lite +{ +DECLARE_SOA_COLUMN(PtBach0, ptBach0, float); //! Transverse momentum of bachelor 0 (GeV/c) +DECLARE_SOA_COLUMN(PtBach1, ptBach1, float); //! Transverse momentum of bachelor 1 (GeV/c) +DECLARE_SOA_COLUMN(MBach0, mBach0, float); //! Invariant mass of bachelor 0 (GeV/c) +DECLARE_SOA_COLUMN(MBach1, mBach1, float); //! Invariant mass of bachelor 1 (GeV/c) +DECLARE_SOA_COLUMN(MBachD0, mBachD0, float); //! Invariant mass of D0 bachelor (of bachelor 0) (GeV/c) +DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate +DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate +DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate +DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) +DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! Sign of candidate +DECLARE_SOA_COLUMN(CosThetaStar, cosThetaStar, float); //! VosThetaStar of candidate (GeV) +DECLARE_SOA_COLUMN(MlScoreBkgBach0, mlScoreBkgBach0, float); //! ML score for background class of charm daughter +DECLARE_SOA_COLUMN(MlScorePromptBach0, mlScorePromptBach0, float); //! ML score for prompt class of charm daughter +DECLARE_SOA_COLUMN(MlScoreNonPromptBach0, mlScoreNonPromptBach0, float); //! ML score for non-prompt class of charm daughter +DECLARE_SOA_COLUMN(ItsNClsProngMinBach0, itsNClsProngMinBach0, int); //! minimum value of number of ITS clusters for the decay daughter tracks of bachelor 0 +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsProngMinBach0, tpcNClsCrossedRowsProngMinBach0, int); //! minimum value of number of TPC crossed rows for the decay daughter tracks of bachelor 0 +DECLARE_SOA_COLUMN(TpcChi2NClProngMaxBach0, tpcChi2NClProngMaxBach0, float); //! maximum value of TPC chi2 for the decay daughter tracks of bachelor 0 +DECLARE_SOA_COLUMN(ItsNClsSoftPi, itsNClsSoftPi, int); //! minimum value of number of ITS clusters for the decay daughter tracks of bachelor 0 +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsSoftPi, tpcNClsCrossedRowsSoftPi, int); //! minimum value of number of TPC crossed rows for the decay daughter tracks of bachelor 0 +DECLARE_SOA_COLUMN(TpcChi2NClSoftPi, tpcChi2NClSoftPi, float); //! maximum value of TPC chi2 for the decay daughter tracks of bachelor 0 +DECLARE_SOA_COLUMN(ItsNClsProngMinBach1, itsNClsProngMinBach1, int); //! minimum value of number of ITS clusters for the decay daughter tracks of bachelor 1 +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsProngMinBach1, tpcNClsCrossedRowsProngMinBach1, int); //! minimum value of number of TPC crossed rows for the decay daughter tracks of bachelor 1 +DECLARE_SOA_COLUMN(TpcChi2NClProngMaxBach1, tpcChi2NClProngMaxBach1, float); //! maximum value of TPC chi2 for the decay daughter tracks of bachelor 1 +DECLARE_SOA_COLUMN(CpaBach1, cpaBach1, float); //! Cosine of Pointing Angle of bachelor 1 +DECLARE_SOA_COLUMN(DcaBach1, dcaBach1, float); //! DCA of bachelor 1 +DECLARE_SOA_COLUMN(RadiusBach1, radiusBach1, float); //! Radius of bachelor 1 +DECLARE_SOA_COLUMN(FlagMcMatch, flagMcMatch, int8_t); //! flag for decay channel classification reconstruction level +DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int); //! debug flag for mis-association at reconstruction level +DECLARE_SOA_COLUMN(Origin, origin, int8_t); //! Flag for origin of MC particle 1=promt, 2=FD +DECLARE_SOA_COLUMN(PtGen, ptGen, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(InvMassGen, invMassGen, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(FlagCharmBach, flagCharmBach, int8_t); //! Flag for charm bachelor classification +DECLARE_SOA_COLUMN(FlagCharmBachInterm, flagCharmBachInterm, int8_t); //! Flag for charm bachelor classification intermediate +} // namespace hf_cand_reso_to_v0_lite + +DECLARE_SOA_TABLE(HfCandDV0Lites, "AOD", "HFCANDDV0LITE", //! Table with some Resonances properties + // Candidate Properties + hf_cand_reso_to_v0_lite::M, + hf_cand_reso_to_v0_lite::Pt, + hf_cand_reso_to_v0_lite::P, + hf_cand_reso_to_v0_lite::Y, + hf_cand_reso_to_v0_lite::Eta, + hf_cand_reso_to_v0_lite::Phi, + hf_cand_reso_to_v0_lite::E, + hf_cand_reso_to_v0_lite::CosThetaStar, + hf_cand_reso_to_v0_lite::Sign, + // Bachelors Properties + hf_cand_reso_to_v0_lite::MBach0, + hf_cand_reso_to_v0_lite::PtBach0, + hf_cand_reso_to_v0_lite::MlScoreBkgBach0, + hf_cand_reso_to_v0_lite::MlScorePromptBach0, + hf_cand_reso_to_v0_lite::MlScoreNonPromptBach0, + hf_cand_reso_to_v0_lite::ItsNClsProngMinBach0, + hf_cand_reso_to_v0_lite::TpcNClsCrossedRowsProngMinBach0, + hf_cand_reso_to_v0_lite::TpcChi2NClProngMaxBach0, + hf_cand_reso_to_v0_lite::ItsNClsSoftPi, + hf_cand_reso_to_v0_lite::TpcNClsCrossedRowsSoftPi, + hf_cand_reso_to_v0_lite::TpcChi2NClSoftPi, + hf_cand_reso_to_v0_lite::MBach1, + hf_cand_reso_to_v0_lite::PtBach1, + hf_cand_reso_to_v0_lite::CpaBach1, + hf_cand_reso_to_v0_lite::DcaBach1, + hf_cand_reso_to_v0_lite::RadiusBach1, + hf_cand_reso_to_v0_lite::ItsNClsProngMinBach1, + hf_cand_reso_to_v0_lite::TpcNClsCrossedRowsProngMinBach1, + hf_cand_reso_to_v0_lite::TpcChi2NClProngMaxBach1, + // MC + hf_cand_reso_to_v0_lite::FlagMcMatch, + hf_cand_reso_to_v0_lite::DebugMcRec, + hf_cand_reso_to_v0_lite::Origin, + hf_cand_reso_to_v0_lite::PtGen, + hf_cand_reso_to_v0_lite::InvMassGen, + hf_cand_reso_to_v0_lite::FlagCharmBach, + hf_cand_reso_to_v0_lite::FlagCharmBachInterm); + +DECLARE_SOA_TABLE(HfGenResoLites, "AOD", "HFGENRESOLITE", //! Table with some B0 properties + hf_cand_reso_to_v0_lite::Pt, + hf_cand_reso_to_v0_lite::Y, + hf_cand_reso_to_v0_lite::Origin, + hf_cand_reso_to_v0_lite::FlagMcMatch); + +} // namespace o2::aod + +enum DecayChannel : uint8_t { + DstarK0s = 0, + DplusK0s, + DplusLambda, + D0Lambda +}; + +struct HfTaskCharmResoToDV0Reduced { + Produces hfCandResoLite; + Produces hfGenResoLite; + + Configurable doWrongSign{"doWrongSign", false, "Flag to enable wrong sign candidates"}; + Configurable ptMinReso{"ptMinReso", -1, "Discard events with smaller pT"}; + Configurable fillTrees{"fillTrees", true, "Fill output Trees"}; + Configurable fillSparses{"fillSparses", false, "Fill output Sparses"}; + Configurable useDeltaMass{"useDeltaMass", true, "Use Delta Mass for resonance invariant Mass calculation"}; + Configurable fillOnlySignal{"fillOnlySignal", false, "Flag to Fill only signal candidates (MC only)"}; + Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; + Configurable yCandRecoMax{"yCandRecoMax", -1, "max. cand. rapidity"}; + Configurable etaTrackMax{"etaTrackMax", 0.8, "max. track pseudo-rapidity for acceptance calculation"}; + Configurable ptTrackMin{"ptTrackMin", 0.1, "min. track transverse momentum for acceptance calculation"}; + Configurable massResoMin{"massResoMin", 0.49, "min. mass of resonance"}; + Configurable massResoMax{"massResoMax", 1.29, "max. mass of resonance"}; + + using ReducedReso3PrV0 = soa::Join; + using ReducedResoDstarV0 = soa::Join; + using ReducedReso2PrV0 = soa::Join; + using ReducedReso3PrV0MC = soa::Join; + using ReducedResoDstarV0MC = soa::Join; + using ReducedReso2PrV0MC = soa::Join; + + // Configurables axis for histos + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisPtProng0{"axisPtProng0", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "prong0 bach. #it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisPtProng1{"axisPtProng1", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "prong1 bach. #it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisInvMassReso{"axisInvMassReso", {200, 2.34, 2.74}, "inv. mass (DV_{0}) (GeV/#it{c}^{2})"}; + ConfigurableAxis axisInvMassProng0{"axisInvMassProng0", {175, 1.70, 2.05}, "inv. mass (D) (GeV/#it{c}^{2})"}; + ConfigurableAxis axisInvMassProng1{"axisInvMassProng1", {80, 0.46, 0.54}, "inv. mass ({V}_{0}) (GeV/#it{c}^{2})"}; + ConfigurableAxis axisCosThetaStar{"axisCosThetaStar", {40, -1, 1}, "cos(#vartheta*)"}; + ConfigurableAxis axisBkgBdtScore{"axisBkgBdtScore", {100, 0, 1}, "bkg BDT Score"}; + ConfigurableAxis axisNonPromptBdtScore{"axisNonPromptBdtScore", {100, 0, 1}, "non-prompt BDT Score"}; + ConfigurableAxis axisEta{"axisEta", {30, -1.5, 1.5}, "pseudorapidity"}; + ConfigurableAxis axisOrigin{"axisOrigin", {3, -0.5, 2.5}, "origin"}; + ConfigurableAxis axisFlag{"axisFlag", {65, -32.5, 32.5}, "mc flag"}; + + // Histogram Registry + HistogramRegistry registry; + + // init + void init(InitContext&) + { + registry.add("hMass", "Charm resonance candidates inv. mass", {HistType::kTH1D, {axisInvMassReso}}); + registry.add("hMassProng0", "D daughters inv. mass", {HistType::kTH1D, {axisInvMassProng0}}); + registry.add("hMassProng1", "V0 daughter inv. mass", {HistType::kTH1D, {axisInvMassProng1}}); + registry.add("hPt", "Charm resonance candidates pT", {HistType::kTH1D, {axisPt}}); + registry.add("hPtProng0", "D daughters pT", {HistType::kTH1D, {axisPtProng0}}); + registry.add("hPtProng1", "V0 daughter pT", {HistType::kTH1D, {axisPtProng1}}); + registry.add("hNPvCont", "Collision number of PV contributors ; N contrib ; entries", {HistType::kTH1D, {{125, -0.5, 249.5}}}); + registry.add("hZvert", "Collision Z Vtx ; z PV [cm] ; entries", {HistType::kTH1D, {{120, -12., 12.}}}); + registry.add("hBz", "Collision Bz ; Bz [T] ; entries", {HistType::kTH1D, {{20, -10., 10.}}}); + registry.add("hSparse", "THn for production studies with cosThStar and BDT scores", HistType::kTHnSparseF, {axisPt, axisPtProng0, axisPtProng1, axisInvMassReso, axisInvMassProng0, axisInvMassProng1, axisCosThetaStar, axisBkgBdtScore, axisNonPromptBdtScore}); + + if (doprocessDstarK0sMC || doprocessDplusK0sMC || doprocessDstarK0sMCWithMl || doprocessDplusK0sMCWithMl || + doprocessDplusLambdaMC || doprocessD0LambdaMC || doprocessDplusLambdaMCWithMl || doprocessD0LambdaMCWithMl) { + // gen histos + registry.add("hYRecPrompt", "Charm resonance candidates pT", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYRecNonPrompt", "Charm resonance candidates pT", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenAll", "Prompt {D_{S}}^j particles (generated);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenPrompt", "Prompt {D_{S}}^j particles (generated);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenPromptWithProngsInAcceptance", "Prompt {D_{S}}^j particles (generated-daughters in acceptance);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenNonPrompt", "NonPrompt {D_{S}}^j particles (generated);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenNonPromptWithProngsInAcceptance", "NonPrompt {D_{S}}^j particles (generated-daughters in acceptance);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + if (fillSparses) { + registry.add("hPtYGenSig", "{D_{S}}^j particles (generated);#it{p}_{T}({D_{S}}^j) (GeV/#it{c});#it{y}({D_{S}}^j)", {HistType::kTHnSparseF, {axisPt, axisEta, axisOrigin, axisFlag}}); + registry.add("hPtYWithProngsInAccepanceGenSig", "{D_{S}}^j particles (generated-daughters in acceptance);#it{p}_{T}({D_{S}}^j) (GeV/#it{c});#it{y}({D_{S}}^j)", {HistType::kTHnSparseF, {axisPt, axisEta, axisOrigin, axisFlag}}); + } + } + } + + // Fill histograms + /// \tparam channel is the decay channel of the Resonance + /// \param candidate is a candidate + /// \param coll is a reduced collision + /// \param bach0 is a bachelor of the candidate + /// \param bach1 is a bachelor of the candidate + template + void fillCand(const Cand& candidate, const Coll& collision, const CharmBach& bach0, const V0Bach& bach1) + { + // Base + float massReso{0}, cosThetaStar{0}; + int8_t sign{0}; + int itsNClsSoftPi{0}, tpcNClsCrossedRowsSoftPi{0}; + float tpcChi2NClSoftPi{0.}; + if constexpr (channel == DecayChannel::DstarK0s) { + sign = bach0.sign(); + massReso = useDeltaMass ? candidate.invMass() + MassDStar : candidate.invMass(); + cosThetaStar = RecoDecay::cosThetaStar(std::array{bach0.pVector(), bach1.pVector()}, std::array{MassDStar, MassK0}, massReso, 0); + itsNClsSoftPi = bach0.itsNClsSoftPi(); + tpcNClsCrossedRowsSoftPi = bach0.tpcNClsCrossedRowsSoftPi(); + tpcChi2NClSoftPi = bach0.tpcChi2NClSoftPi(); + } else if constexpr (channel == DecayChannel::DplusK0s) { + sign = bach0.sign(); + massReso = useDeltaMass ? candidate.invMass() + MassDPlus : candidate.invMass(); + cosThetaStar = RecoDecay::cosThetaStar(std::array{bach0.pVector(), bach1.pVector()}, std::array{MassDPlus, MassK0}, massReso, 0); + } else if constexpr (channel == DecayChannel::DplusLambda) { + sign = bach0.sign(); + massReso = useDeltaMass ? candidate.invMass() + MassDPlus : candidate.invMass(); + cosThetaStar = RecoDecay::cosThetaStar(std::array{bach0.pVector(), bach1.pVector()}, std::array{MassDPlus, MassLambda0}, massReso, 0); + } else if constexpr (channel == DecayChannel::D0Lambda) { + massReso = useDeltaMass ? candidate.invMass() + MassD0 : candidate.invMass(); + cosThetaStar = RecoDecay::cosThetaStar(std::array{bach0.pVector(), bach1.pVector()}, std::array{MassD0, MassLambda0}, massReso, 0); + } + float y = RecoDecay::y(std::array{candidate.px(), candidate.py(), candidate.pz()}, massReso); + float eta = RecoDecay::eta(std::array{candidate.px(), candidate.py(), candidate.pz()}); + float phi = RecoDecay::phi(candidate.px(), candidate.py()); + float p = RecoDecay::p(std::array{candidate.px(), candidate.py(), candidate.pz()}); + float e = RecoDecay::e(std::array{candidate.px(), candidate.py(), candidate.pz()}, massReso); + + // MC Rec + float ptGen{-1.}, invMassGen{-1}; + int8_t origin{0}, flagMcMatchRec{0}, flagCharmBach{0}, flagCharmBachInterm{0}; + int debugMcRec{-1}; + if constexpr (doMc) { + ptGen = candidate.ptGen(); + origin = candidate.origin(); + flagMcMatchRec = candidate.flagMcMatchRec(); + debugMcRec = candidate.debugMcRec(); + invMassGen = candidate.invMassGen(); + flagCharmBach = candidate.flagMcMatchRecD(); + flagCharmBachInterm = candidate.flagMcMatchChanD(); + if (fillOnlySignal) { + if (channel == DecayChannel::DstarK0s && + !hf_decay::hf_cand_reso::particlesToDstarK0s.contains(static_cast(std::abs(flagMcMatchRec)))) { + return; + } else if (channel == DecayChannel::DplusK0s && + !hf_decay::hf_cand_reso::particlesToDplusK0s.contains(static_cast(std::abs(flagMcMatchRec)))) { + return; + } else if (channel == DecayChannel::DplusLambda && + !hf_decay::hf_cand_reso::particlesToDplusLambda.contains(static_cast(std::abs(flagMcMatchRec)))) { + return; + } else if (channel == DecayChannel::D0Lambda && + !hf_decay::hf_cand_reso::particlesToD0Lambda.contains(static_cast(std::abs(flagMcMatchRec)))) { + return; + } + } + if (origin == RecoDecay::OriginType::Prompt) { + registry.fill(HIST("hYRecPrompt"), candidate.pt(), y); + } else if (origin == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("hYRecNonPrompt"), candidate.pt(), y); + } + } + + // Ml + float mlScoreBkg{-1.}, mlScorePrompt{-1.}, mlScoreNonPrompt{-1.}; + if constexpr (withMl) { + if constexpr (channel == DecayChannel::D0Lambda) { + if (TESTBIT(bach1.v0Type(), BachelorType::Lambda) && !doWrongSign) { + mlScoreBkg = bach0.mlScoreBkgMassHypo0(); + mlScorePrompt = bach0.mlScorePromptMassHypo0(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo0(); + } else if (TESTBIT(bach1.v0Type(), BachelorType::AntiLambda) && !doWrongSign) { + mlScoreBkg = bach0.mlScoreBkgMassHypo1(); + mlScorePrompt = bach0.mlScorePromptMassHypo1(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo1(); + } else if (TESTBIT(bach1.v0Type(), BachelorType::Lambda) && doWrongSign) { + mlScoreBkg = bach0.mlScoreBkgMassHypo1(); + mlScorePrompt = bach0.mlScorePromptMassHypo1(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo1(); + } else if (TESTBIT(bach1.v0Type(), BachelorType::AntiLambda) && doWrongSign) { + mlScoreBkg = bach0.mlScoreBkgMassHypo0(); + mlScorePrompt = bach0.mlScorePromptMassHypo0(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo0(); + } + } else { + mlScoreBkg = bach0.mlScoreBkgMassHypo0(); + mlScorePrompt = bach0.mlScorePromptMassHypo0(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo0(); + } + } + // Collision properties + registry.fill(HIST("hNPvCont"), collision.numContrib()); + registry.fill(HIST("hZvert"), collision.posZ()); + registry.fill(HIST("hBz"), collision.bz()); + // Candidate properties + registry.fill(HIST("hMass"), candidate.invMass()); + registry.fill(HIST("hMassProng0"), candidate.invMassProng0()); + registry.fill(HIST("hMassProng1"), candidate.invMassProng1()); + registry.fill(HIST("hPt"), candidate.pt()); + registry.fill(HIST("hPtProng0"), candidate.ptProng0()); + registry.fill(HIST("hPtProng1"), candidate.ptProng1()); + if (fillSparses) { + registry.fill(HIST("hSparse"), candidate.pt(), candidate.ptProng0(), candidate.ptProng1(), candidate.invMass(), candidate.invMassProng0(), candidate.invMassProng1(), cosThetaStar, mlScoreBkg, mlScoreNonPrompt); + } + if (fillTrees) { + hfCandResoLite( + candidate.invMass(), + candidate.pt(), + p, + y, + eta, + phi, + e, + cosThetaStar, + sign, + // Bachelors Properties + candidate.invMassProng0(), + bach0.pt(), + mlScoreBkg, + mlScorePrompt, + mlScoreNonPrompt, + bach0.itsNClsProngMin(), + bach0.tpcNClsCrossedRowsProngMin(), + bach0.tpcChi2NClProngMax(), + itsNClsSoftPi, + tpcNClsCrossedRowsSoftPi, + tpcChi2NClSoftPi, + candidate.invMassProng1(), + bach1.pt(), + bach1.cpa(), + bach1.dca(), + bach1.v0Radius(), + bach1.itsNClsProngMin(), + bach1.tpcNClsCrossedRowsProngMin(), + bach1.tpcChi2NClProngMax(), + // MC + flagMcMatchRec, + debugMcRec, + origin, + ptGen, + invMassGen, + flagCharmBach, + flagCharmBachInterm); + } + } // fillCand + + // Process data + /// \tparam channel is the decay channel of the Resonance + /// \param Coll is the reduced collisions table + /// \param CharmBach is the reduced 3 prong table + /// \param V0Bach is the reduced v0 table + /// \param Cand is the candidates table + template + void processData(Coll const&, Candidates const& candidates, CharmBach const&, aod::HfRedVzeros const&) + { + for (const auto& cand : candidates) { + if (ptMinReso >= 0 && cand.pt() < ptMinReso) { + continue; + } + if ((massResoMin >= 0 && cand.invMass() < massResoMin) || + (massResoMax >= 0 && cand.invMass() > massResoMax)) { + continue; + } + if (doWrongSign && cand.isWrongSign() == 0) { + continue; + } else if (!doWrongSign && cand.isWrongSign() != 0) { + continue; + } + + float massReso{0}; + if (useDeltaMass) { + switch (channel) { + case DecayChannel::DstarK0s: + massReso = cand.invMass() + MassDStar; + break; + case DecayChannel::DplusK0s: + massReso = cand.invMass() + MassDPlus; + break; + case DecayChannel::DplusLambda: + massReso = cand.invMass() + MassDPlus; + break; + case DecayChannel::D0Lambda: + massReso = cand.invMass() + MassD0; + break; + default: + break; + } + } else { + massReso = cand.invMass(); + } + if (yCandRecoMax >= 0. && std::abs(RecoDecay::y(std::array{cand.px(), cand.py(), cand.pz()}, massReso)) > yCandRecoMax) { + continue; + } + auto coll = cand.template hfRedCollision_as(); + auto bach0 = cand.template prong0_as(); + auto bach1 = cand.template prong1_as(); + fillCand(cand, coll, bach0, bach1); + } + } + + /// Selection of resonance daughters in geometrical acceptance + /// \param etaProng is the pseudorapidity of Resonance prong + /// \param ptProng is the pT of Resonance prong + /// \return true if prong is in geometrical acceptance + template + bool isProngInAcceptance(const T& etaProng, const T& ptProng) + { + return std::abs(etaProng) <= etaTrackMax && ptProng >= ptTrackMin; + } + + /// Fill particle histograms (gen MC truth) + template + void fillCandMcGen(aod::HfMcGenRedResos const& mcParticles) + { + for (const auto& particle : mcParticles) { + auto ptParticle = particle.ptTrack(); + auto yParticle = particle.yTrack(); + auto originParticle = particle.origin(); + auto flag = particle.flagMcMatchGen(); + std::array ptProngs = {particle.ptProng0(), particle.ptProng1()}; + std::array etaProngs = {particle.etaProng0(), particle.etaProng1()}; + bool prongsInAcc = isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1]); + if (channel == DecayChannel::DstarK0s && + !hf_decay::hf_cand_reso::particlesToDstarK0s.contains(static_cast(std::abs(flag)))) { + continue; + } else if (channel == DecayChannel::DplusK0s && + !hf_decay::hf_cand_reso::particlesToDplusK0s.contains(static_cast(std::abs(flag)))) { + continue; + } else if (channel == DecayChannel::DplusLambda && + !hf_decay::hf_cand_reso::particlesToDplusLambda.contains(static_cast(std::abs(flag)))) { + continue; + } else if (channel == DecayChannel::D0Lambda && + !hf_decay::hf_cand_reso::particlesToD0Lambda.contains(static_cast(std::abs(flag)))) { + continue; + } + registry.fill(HIST("hYGenAll"), ptParticle, yParticle); + if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { + continue; + } + if (originParticle == RecoDecay::OriginType::Prompt) { // prompt particles + registry.fill(HIST("hYGenPrompt"), ptParticle, yParticle); + if (prongsInAcc) { + registry.fill(HIST("hYGenPromptWithProngsInAcceptance"), ptParticle, yParticle); + } + } else if (originParticle == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("hYGenNonPrompt"), ptParticle, yParticle); + if (prongsInAcc) { + registry.fill(HIST("hYGenNonPromptWithProngsInAcceptance"), ptParticle, yParticle); + } + } + if (fillSparses) { + registry.fill(HIST("hPtYGenSig"), ptParticle, yParticle, originParticle, flag); + if (prongsInAcc) { + registry.fill(HIST("hPtYWithProngsInAccepanceGenSig"), ptParticle, yParticle, originParticle, flag); + } + } + if (fillTrees) { + hfGenResoLite(ptParticle, yParticle, originParticle, flag); + } + } + } // fillCandMcGen + + // process functions + void processDstarK0sData(aod::HfRedCollisions const& collisions, + ReducedResoDstarV0 const& candidates, + aod::HfRedDstarNoTrks const& charmBachs, + aod::HfRedVzeros const& v0Bachs) + { + processData(collisions, candidates, charmBachs, v0Bachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDstarK0sData, "Process data for DstarK0s analysis", true); + + void processDplusK0sData(aod::HfRedCollisions const& collisions, + ReducedReso3PrV0 const& candidates, + aod::HfRed3PrNoTrks const& charmBachs, + aod::HfRedVzeros const& v0Bachs) + { + processData(collisions, candidates, charmBachs, v0Bachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDplusK0sData, "Process data for DplusK0s analysis", false); + + void processDplusLambdaData(aod::HfRedCollisions const& collisions, + ReducedReso3PrV0 const& candidates, + aod::HfRed3PrNoTrks const& charmBachs, + aod::HfRedVzeros const& v0Bachs) + { + processData(collisions, candidates, charmBachs, v0Bachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDplusLambdaData, "Process data for DplusLambda analysis", false); + + void processD0LambdaData(aod::HfRedCollisions const& collisions, + ReducedReso2PrV0 const& candidates, + aod::HfRed2PrNoTrks const& charmBachs, + aod::HfRedVzeros const& v0Bachs) + { + processData(collisions, candidates, charmBachs, v0Bachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processD0LambdaData, "Process data for D0Lambda analysis", false); + + // Process data with ML + void processDstarK0sDataWithMl(aod::HfRedCollisions const& collisions, + ReducedResoDstarV0 const& candidates, + soa::Join const& charmBachs, + aod::HfRedVzeros const& v0Bachs) + { + processData(collisions, candidates, charmBachs, v0Bachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDstarK0sDataWithMl, "Process data for DstarK0s analysis with Ml", false); + + void processDplusK0sDataWithMl(aod::HfRedCollisions const& collisions, + ReducedReso3PrV0 const& candidates, + soa::Join const& charmBachs, + aod::HfRedVzeros const& v0Bachs) + { + processData(collisions, candidates, charmBachs, v0Bachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDplusK0sDataWithMl, "Process data for DplusK0s analysis with Ml", false); + + void processDplusLambdaDataWithMl(aod::HfRedCollisions const& collisions, + ReducedReso3PrV0 const& candidates, + soa::Join const& charmBachs, + aod::HfRedVzeros const& v0Bachs) + { + processData(collisions, candidates, charmBachs, v0Bachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDplusLambdaDataWithMl, "Process data for DplusLambda analysis with Ml", false); + + void processD0LambdaDataWithMl(aod::HfRedCollisions const& collisions, + ReducedReso2PrV0 const& candidates, + soa::Join const& charmBachs, + aod::HfRedVzeros const& v0Bachs) + { + processData(collisions, candidates, charmBachs, v0Bachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processD0LambdaDataWithMl, "Process data for D0Lambda analysis with Ml", false); + + // MC + void processDstarK0sMC(aod::HfRedCollisions const& collisions, + ReducedResoDstarV0MC const& candidates, + aod::HfRedDstarNoTrks const& charmBachs, + aod::HfRedVzeros const& v0Bachs, + aod::HfMcGenRedResos const& mcParticles) + { + processData(collisions, candidates, charmBachs, v0Bachs); + fillCandMcGen(mcParticles); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDstarK0sMC, "Process MC for DstarK0s analysis", false); + + void processDplusK0sMC(aod::HfRedCollisions const& collisions, + ReducedReso3PrV0MC const& candidates, + aod::HfRed3PrNoTrks const& charmBachs, + aod::HfRedVzeros const& v0Bachs, + aod::HfMcGenRedResos const& mcParticles) + { + processData(collisions, candidates, charmBachs, v0Bachs); + fillCandMcGen(mcParticles); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDplusK0sMC, "Process MC for DplusK0s analysis", false); + + void processDplusLambdaMC(aod::HfRedCollisions const& collisions, + ReducedReso3PrV0MC const& candidates, + aod::HfRed3PrNoTrks const& charmBachs, + aod::HfRedVzeros const& v0Bachs, + aod::HfMcGenRedResos const& mcParticles) + { + processData(collisions, candidates, charmBachs, v0Bachs); + fillCandMcGen(mcParticles); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDplusLambdaMC, "Process MC for DplusLambda analysis", false); + + void processD0LambdaMC(aod::HfRedCollisions const& collisions, + ReducedReso2PrV0MC const& candidates, + aod::HfRed2PrNoTrks const& charmBachs, + aod::HfRedVzeros const& v0Bachs, + aod::HfMcGenRedResos const& mcParticles) + { + processData(collisions, candidates, charmBachs, v0Bachs); + fillCandMcGen(mcParticles); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processD0LambdaMC, "Process MC for D0Lambda analysis", false); + + // MC with Ml + void processDstarK0sMCWithMl(aod::HfRedCollisions const& collisions, + ReducedResoDstarV0MC const& candidates, + soa::Join const& charmBachs, + aod::HfRedVzeros const& v0Bachs, + aod::HfMcGenRedResos const& charmBachsMc) + { + processData(collisions, candidates, charmBachs, v0Bachs); + fillCandMcGen(charmBachsMc); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDstarK0sMCWithMl, "Process MC for DstarK0s analysis with Ml", false); + + void processDplusK0sMCWithMl(aod::HfRedCollisions const& collisions, + ReducedReso3PrV0MC const& candidates, + soa::Join const& charmBachs, + aod::HfRedVzeros const& v0Bachs, + aod::HfMcGenRedResos const& mcParticles) + { + processData(collisions, candidates, charmBachs, v0Bachs); + fillCandMcGen(mcParticles); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDplusK0sMCWithMl, "Process MC for DplusK0s analysis with Ml", false); + + void processDplusLambdaMCWithMl(aod::HfRedCollisions const& collisions, + ReducedReso3PrV0MC const& candidates, + soa::Join const& charmBachs, + aod::HfRedVzeros const& v0Bachs, + aod::HfMcGenRedResos const& mcParticles) + { + processData(collisions, candidates, charmBachs, v0Bachs); + fillCandMcGen(mcParticles); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDplusLambdaMCWithMl, "Process MC for DplusLambda analysis with Ml", false); + + void processD0LambdaMCWithMl(aod::HfRedCollisions const& collisions, + ReducedReso2PrV0MC const& candidates, + soa::Join const& charmBachs, + aod::HfRedVzeros const& v0Bachs, + aod::HfMcGenRedResos const& mcParticles) + { + processData(collisions, candidates, charmBachs, v0Bachs); + fillCandMcGen(mcParticles); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processD0LambdaMCWithMl, "Process MC for D0Lambda analysis with Ml", false); + +}; // struct HfTaskCharmResoToDV0Reduced +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/Utils/utilsMcMatching.h b/PWGHF/Utils/utilsMcMatching.h index 31f9396e021..bac650d36d4 100644 --- a/PWGHF/Utils/utilsMcMatching.h +++ b/PWGHF/Utils/utilsMcMatching.h @@ -176,6 +176,45 @@ inline std::unordered_map> getDecayChan } } // namespace hf_cand_3prong +namespace hf_cand_reso +{ +const std::unordered_map particlesToDstarK0s = { + {DecayChannelMain::Ds1ToDstarK0s, constants::physics::Pdg::kDS1}, + {DecayChannelMain::Ds2starToDstarK0s, constants::physics::Pdg::kDS2Star}, + {DecayChannelMain::Ds1star2700ToDstarK0s, constants::physics::Pdg::kDS1Star2700}, + {DecayChannelMain::Ds1star2860ToDstarK0s, constants::physics::Pdg::kDS1Star2860}, + {DecayChannelMain::Ds3star2860ToDstarK0s, constants::physics::Pdg::kDS3Star2860}}; +const std::unordered_map particlesToDplusK0s = { + {DecayChannelMain::Ds2starToDplusK0s, constants::physics::Pdg::kDS2Star}}; +const std::unordered_map particlesToDplusLambda = { + {DecayChannelMain::Xic3055plusToDplusLambda, constants::physics::Pdg::kXiC3055Plus}, + {DecayChannelMain::Xic3080plusToDplusLambda, constants::physics::Pdg::kXiC3080Plus}}; +const std::unordered_map particlesToD0Lambda = { + {DecayChannelMain::Xic3055zeroToD0Lambda, constants::physics::Pdg::kXiC3055_0}, + {DecayChannelMain::Xic3080zeroToD0Lambda, constants::physics::Pdg::kXiC3080_0}}; +const std::unordered_map particlesToDstarPi = { + {DecayChannelMain::D1zeroToDstarPi, constants::physics::Pdg::kD10}, + {DecayChannelMain::D2starzeroToDstarPi, constants::physics::Pdg::kD2Star0}}; +const std::unordered_map particlesToDplusPi = { + {DecayChannelMain::D2starzeroToDplusPi, constants::physics::Pdg::kD2Star0}}; +const std::unordered_map particlesToD0Pi = { + {DecayChannelMain::D2starplusToD0Pi, constants::physics::Pdg::kD2StarPlus}}; +const std::unordered_map particlesToD0Kplus = { + {DecayChannelMain::Ds2starToD0Kplus, constants::physics::Pdg::kDS2Star}}; + +enum PartialMatchMc : uint8_t { + D0Matched = 0, + DstarMatched, + DplusMatched, + K0Matched, + LambdaMatched, + PionMatched, + KaonMatched, + ProtonMatched, + ResoPartlyMatched +}; +} // namespace hf_cand_reso + /// Compare an array of PDG codes with an expected array /// \tparam N size of the arrays to be compared /// \param arrPdgTested array of PDG codes to be tested