Skip to content

Commit 1dd083c

Browse files
[PWGHF] Add flags and additional columns to the full c–d table for possible correlated-background studies (#17699)
1 parent 2a972e1 commit 1dd083c

2 files changed

Lines changed: 72 additions & 47 deletions

File tree

PWGHF/D2H/Tasks/taskCd.cxx

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ namespace full
6969
{
7070
// Candidate kinematics
7171
DECLARE_SOA_COLUMN(MassCd, massCd, float); //! Invariant mass of cd candidate (GeV/c^2)
72-
DECLARE_SOA_COLUMN(MassLc, massLc, float); //! Invariant mass of lc candidate (GeV/c^2)
72+
DECLARE_SOA_COLUMN(MassLc, massLc, float); //! Invariant mass under the p K pi hypothesis (GeV/c^2)
7373
DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c)
7474
DECLARE_SOA_COLUMN(Eta, eta, float); //! eta of candidate (GeV/c)
7575
DECLARE_SOA_COLUMN(Phi, phi, float); //! phi of candidate (GeV/c)
@@ -114,13 +114,15 @@ DECLARE_SOA_COLUMN(NTpcSignalsKa, nTpcSignalsKa, float); //! Number o
114114
DECLARE_SOA_COLUMN(NItsSignalsDe, nItsSignalsDe, float); //! Number of ITS signas
115115
DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int8_t); //! Candidates falg
116116
DECLARE_SOA_COLUMN(CandidateSign, candidateSign, int8_t); //! Candidates sign
117-
DECLARE_SOA_COLUMN(FlagMc, flagMc, int8_t); //! MC matching flag
117+
DECLARE_SOA_COLUMN(FlagMc, flagMc, int8_t); //! Main MC decay-channel flag; 0 for unmatched candidates
118+
DECLARE_SOA_COLUMN(IsCandidateSwapped, isCandidateSwapped, int8_t); //! MC-matched prong permutation; -1 for data
118119
DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! MC origin for reconstructed candidates
119120
DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); //! Resonant MC decay channel for reconstructed candidates
120121
DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! MC origin for generated particles
121122
DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); //! Resonant MC decay channel for generated candidates
122123
DECLARE_SOA_COLUMN(CtGen, ctGen, float); //! Generated ct computed wrt to c-deuteron production vertex, which can be either PV (prompt) or B-hadron decay vertex (non-prompt)
123124
DECLARE_SOA_COLUMN(CtRec, ctRec, float); //! Reconstructed ct computed wrt to PV
125+
DECLARE_SOA_COLUMN(NumPvContributors, numPvContributors, uint16_t); //! Number of contributors to the primary vertex
124126
DECLARE_SOA_COLUMN(Cent, cent, float); //! Centrality
125127
DECLARE_SOA_COLUMN(VtxZ, vtxZ, float); //! Vertex Z
126128
DECLARE_SOA_COLUMN(GIndexCol, gIndexCol, int); //! Global index for the collision
@@ -192,9 +194,11 @@ DECLARE_SOA_TABLE(HfCandCdFull, "AOD", "HFCANDCDFULL",
192194
full::CandidateSelFlag,
193195
full::CandidateSign,
194196
full::FlagMc,
197+
full::IsCandidateSwapped,
195198
full::OriginMcRec,
196199
full::FlagMcDecayChanRec,
197200
full::CtGen,
201+
full::NumPvContributors,
198202
full::Cent,
199203
full::VtxZ,
200204
full::GIndexCol,
@@ -209,6 +213,7 @@ DECLARE_SOA_TABLE(HfCandCdGen, "AOD", "HFCANDCDGEN",
209213
full::OriginMcGen,
210214
full::FlagMcDecayChanGen,
211215
full::CtGen,
216+
full::NumPvContributors,
212217
full::Cent,
213218
full::VtxZ,
214219
full::McCollisionId);
@@ -231,6 +236,9 @@ struct HfTaskCd {
231236
Configurable<bool> cfgCutOnDeuteronDcaOrdering{"cfgCutOnDeuteronDcaOrdering", false, "Require deuteron DCA to be smaller than kaon and pion DCAs"};
232237
Configurable<float> cfgMinDeuteronDcaPreselection{"cfgMinDeuteronDcaPreselection", 0.004, "Minimum deuteron DCA for preselection (cm)"};
233238
Configurable<float> cfgMaxDeuteronTofPidPreselection{"cfgMaxDeuteronTofPidPreselection", 5, "Maximum |nSigma TOF| for deuteron preselection"};
239+
Configurable<bool> fillMcCorrelatedBackgrounds{"fillMcCorrelatedBackgrounds", false, "Store selected MC candidates matched to a supported decay channel other than c-deuteron"};
240+
Configurable<bool> fillMcCombinatorialBackground{"fillMcCombinatorialBackground", false, "Store selected MC candidates with flagMcMatchRec equal to zero"};
241+
Configurable<bool> acceptCandidatesWithoutCdFlag{"acceptCandidatesWithoutCdFlag", false, "Accept selected candidates without the Cd skim bit; intended for MC reflection studies"};
234242

235243
SliceCache cache;
236244

@@ -263,9 +271,9 @@ struct HfTaskCd {
263271
ConfigurableAxis thnConfigAxisNumPvContr{"thnConfigAxisNumPvContr", {200, -0.5, 199.5}, "Number of PV contributors"};
264272
ConfigurableAxis thnConfigAxisCt{"thnConfigAxisCt", {500, 0., 5000.}, ""};
265273

266-
constexpr static std::string_view SignalFolders[] = {"signal", "prompt", "nonprompt"};
267-
constexpr static std::string_view SignalSuffixes[] = {"", "Prompt", "NonPrompt"};
268-
const float cmToMum = 1.e4;
274+
static constexpr std::array<std::string_view, 3> SignalFolders = {"signal", "prompt", "nonprompt"};
275+
static constexpr std::array<std::string_view, 3> SignalSuffixes = {"", "Prompt", "NonPrompt"};
276+
static constexpr float CmToMum = 1.e4f;
269277

270278
enum SignalClasses : int {
271279
Signal = 0,
@@ -332,6 +340,9 @@ struct HfTaskCd {
332340
addHistogramsGen("hPt", "#it{p}_{T}^{gen.} (GeV/#it{c})", "entries", {HistType::kTH1D, {{360, 0., 36.}}});
333341
if (!isData) {
334342
registry.add("MC/generated/signal/hPtGenSig", "3-prong candidates (matched);#it{p}_{T}^{gen.} (GeV/#it{c});entries", {HistType::kTH1D, {{360, 0., 36.}}});
343+
registry.add("MC/reconstructed/allCandidates/hFlagMcMatchRec", "Selected 3-prong candidates;MC decay-channel flag;entries", {HistType::kTH1D, {{49, -24.5, 24.5}}});
344+
registry.add("MC/reconstructed/allCandidates/hMassCdVsFlagMcMatchRec", "Selected 3-prong candidates;inv. mass (d K #pi) (GeV/#it{c}^{2});MC decay-channel flag", {HistType::kTH2F, {{400, 2.4, 4.4}, {49, -24.5, 24.5}}});
345+
registry.add("MC/reconstructed/allCandidates/hMassPKPiVsFlagMcMatchRec", "Selected 3-prong candidates;inv. mass (p K #pi) (GeV/#it{c}^{2});MC decay-channel flag", {HistType::kTH2F, {{400, 1.6, 3.2}, {49, -24.5, 24.5}}});
335346
}
336347
addHistogramsRec("hPtProng0", "prong 0 #it{p}_{T} (GeV/#it{c})", "entries", {HistType::kTH1D, {{360, 0., 36.}}});
337348
addHistogramsRec("hPtProng1", "prong 1 #it{p}_{T} (GeV/#it{c})", "entries", {HistType::kTH1D, {{360, 0., 36.}}});
@@ -496,25 +507,39 @@ struct HfTaskCd {
496507
const int64_t timeStamp = bc.timestamp();
497508

498509
for (const auto& candidate : groupedCdCandidates) {
499-
if (candidate.flagMcMatchRec() == 0) { // we skip combinatorial background
510+
const int absFlagMc = std::abs(candidate.flagMcMatchRec());
511+
const bool isTrueCd = absFlagMc == hf_decay::hf_cand_3prong::DecayChannelMain::CDeuteronToDeKPi;
512+
const bool keepCorrelatedBackground = fillMcCorrelatedBackgrounds && absFlagMc != 0 && !isTrueCd;
513+
const bool keepCombinatorialBackground = fillMcCombinatorialBackground && absFlagMc == 0;
514+
if (!isTrueCd && !keepCorrelatedBackground && !keepCombinatorialBackground) {
500515
continue;
501516
}
502-
if (!TESTBIT(candidate.hfflag(), aod::hf_cand_3prong::DecayType::CdToDeKPi)) {
517+
if (!acceptCandidatesWithoutCdFlag && !TESTBIT(candidate.hfflag(), aod::hf_cand_3prong::DecayType::CdToDeKPi)) {
503518
continue;
504519
}
505520
const auto yCd = RecoDecay::y(candidate.pVector(), o2::constants::physics::MassCDeuteron);
506521
if (yCandRecoMax >= 0. && std::abs(yCd) > yCandRecoMax) {
507522
continue;
508523
}
509524

525+
registry.fill(HIST("MC/reconstructed/allCandidates/hFlagMcMatchRec"), candidate.flagMcMatchRec());
526+
if (candidate.isSelCdToDeKPi() >= selectionFlagCd) {
527+
registry.fill(HIST("MC/reconstructed/allCandidates/hMassCdVsFlagMcMatchRec"), HfHelper::invMassCdToDeKPi(candidate), candidate.flagMcMatchRec());
528+
registry.fill(HIST("MC/reconstructed/allCandidates/hMassPKPiVsFlagMcMatchRec"), HfHelper::invMassLcToPKPi(candidate), candidate.flagMcMatchRec());
529+
}
530+
if (candidate.isSelCdToPiKDe() >= selectionFlagCd) {
531+
registry.fill(HIST("MC/reconstructed/allCandidates/hMassCdVsFlagMcMatchRec"), HfHelper::invMassCdToPiKDe(candidate), candidate.flagMcMatchRec());
532+
registry.fill(HIST("MC/reconstructed/allCandidates/hMassPKPiVsFlagMcMatchRec"), HfHelper::invMassLcToPiKP(candidate), candidate.flagMcMatchRec());
533+
}
534+
510535
float ctGen{-1.f}, ptGen{-1.f};
511536
int pdgCodeProng0{0};
512-
if (std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::CDeuteronToDeKPi) {
537+
if (isTrueCd) {
513538
const auto& mcParticleProng0 = candidate.template prong0_as<HFTracksMc>().template mcParticle_as<CandCdMcGen>();
514539
pdgCodeProng0 = std::abs(mcParticleProng0.pdgCode());
515540
const auto indexMother = RecoDecay::getMother(mcParticles, mcParticleProng0, o2::constants::physics::Pdg::kCDeuteron, true);
516541
const auto particleMother = mcParticles.rawIteratorAt(indexMother);
517-
ctGen = RecoDecay::ct(std::array{particleMother.px(), particleMother.py(), particleMother.pz()}, RecoDecay::distance(std::array{particleMother.vx(), particleMother.vy(), particleMother.vz()}, std::array{mcParticleProng0.vx(), mcParticleProng0.vy(), mcParticleProng0.vz()}), o2::constants::physics::MassCDeuteron) * cmToMum;
542+
ctGen = RecoDecay::ct(std::array{particleMother.px(), particleMother.py(), particleMother.pz()}, RecoDecay::distance(std::array{particleMother.vx(), particleMother.vy(), particleMother.vz()}, std::array{mcParticleProng0.vx(), mcParticleProng0.vy(), mcParticleProng0.vz()}), o2::constants::physics::MassCDeuteron) * CmToMum;
518543
ptGen = particleMother.pt();
519544
}
520545

@@ -566,7 +591,7 @@ struct HfTaskCd {
566591
candidate.decayLength(), candidate.cpa(), candidate.chi2PCA(),
567592
nSigmaTpcDe, nSigmaTpcPr, nSigmaItsDe, nSigmaTofDe,
568593
tofBetaDe, tpcInnerParamDe, tofExpMomDe,
569-
candidate.ct(o2::constants::physics::MassCDeuteron) * cmToMum,
594+
candidate.ct(o2::constants::physics::MassCDeuteron) * CmToMum,
570595
candFlag, candSign, candidate.flagMcMatchRec(), candidate.originMcRec(),
571596
candidate.flagMcDecayChanRec(), ctGen, o2::hf_centrality::getCentralityColl(collision));
572597
}
@@ -581,23 +606,34 @@ struct HfTaskCd {
581606
nSigmaTpcDe, nSigmaTpcPr, nSigmaItsDe, nSigmaTofDe,
582607
tofBetaDe, tpcInnerParamDe, tofExpMomDe,
583608
nSigmaTpcPi, nSigmaTofPi, nSigmaTpcKa, nSigmaTofKa,
584-
candidate.ct(o2::constants::physics::MassCDeuteron) * cmToMum,
585-
candFlag, candSign, candidate.flagMcMatchRec(), candidate.originMcRec(),
586-
candidate.flagMcDecayChanRec(), ctGen, o2::hf_centrality::getCentralityColl(collision),
609+
candidate.ct(o2::constants::physics::MassCDeuteron) * CmToMum,
610+
candFlag, candSign, candidate.flagMcMatchRec(), candidate.isCandidateSwapped(), candidate.originMcRec(),
611+
candidate.flagMcDecayChanRec(), ctGen, collision.numContrib(), o2::hf_centrality::getCentralityColl(collision),
587612
collision.posZ(), collision.globalIndex(), timeStamp);
588613
}
589614
};
590615

591-
// For MC, retain only the hypothesis that matches the true deuteron prong.
592-
if (selDeKPi && pdgCodeProng0 == o2::constants::physics::Pdg::kDeuteron) {
593-
writeMcHypothesis(true);
594-
}
595-
if (selPiKDe && pdgCodeProng0 == kPiPlus) {
596-
writeMcHypothesis(false);
616+
if (isTrueCd) {
617+
// For signal MC, retain only the hypothesis that matches the true deuteron prong.
618+
if (selDeKPi && pdgCodeProng0 == o2::constants::physics::Pdg::kDeuteron) {
619+
writeMcHypothesis(true);
620+
}
621+
if (selPiKDe && pdgCodeProng0 == kPiPlus) {
622+
writeMcHypothesis(false);
623+
}
624+
} else {
625+
// Reflection and combinatorial candidates have no true deuteron prong.
626+
// Retain every Cd hypothesis accepted by the selector and distinguish them with CandidateSelFlag.
627+
if (selDeKPi) {
628+
writeMcHypothesis(true);
629+
}
630+
if (selPiKDe) {
631+
writeMcHypothesis(false);
632+
}
597633
}
598634
}
599635

600-
if (std::abs(candidate.flagMcMatchRec()) != hf_decay::hf_cand_3prong::DecayChannelMain::CDeuteronToDeKPi) {
636+
if (!isTrueCd) {
601637
continue;
602638
}
603639

@@ -661,7 +697,7 @@ struct HfTaskCd {
661697
const bool isPrompt = particle.originMcGen() == 0;
662698
const float ptGenB = isPrompt ? -1.f : mcParticles.rawIteratorAt(particle.idxBhadMotherPart()).pt();
663699
const auto firstDau = particle.template daughters_as<CandCdMcGen>().begin();
664-
const float ctGen = RecoDecay::ct(std::array{particle.px(), particle.py(), particle.pz()}, RecoDecay::distance(std::array{particle.vx(), particle.vy(), particle.vz()}, std::array{firstDau.vx(), firstDau.vy(), firstDau.vz()}), o2::constants::physics::MassCDeuteron) * cmToMum;
700+
const float ctGen = RecoDecay::ct(std::array{particle.px(), particle.py(), particle.pz()}, RecoDecay::distance(std::array{particle.vx(), particle.vy(), particle.vz()}, std::array{firstDau.vx(), firstDau.vy(), firstDau.vz()}), o2::constants::physics::MassCDeuteron) * CmToMum;
665701

666702
fillHistogramsGen<Signal>(particle, yGen);
667703
if (isPrompt) {
@@ -684,6 +720,7 @@ struct HfTaskCd {
684720
particle.originMcGen(),
685721
particle.flagMcDecayChanGen(),
686722
ctGen,
723+
numPvContributors,
687724
cent,
688725
vtxZ,
689726
particle.mcCollision().globalIndex());
@@ -849,7 +886,7 @@ struct HfTaskCd {
849886
tofBetaDe, tpcInnerParamDe, tofExpMomDe,
850887
nSigmaTpcPi, nSigmaTofPi, nSigmaTpcKa, nSigmaTofKa,
851888
candidate.ct(o2::constants::physics::MassCDeuteron),
852-
candFlag, candSign, 0, 0, -1, -1.f, cent,
889+
candFlag, candSign, 0, -1, 0, 0, -1.f, collision.numContrib(), cent,
853890
collision.posZ(), collision.globalIndex(), timeStamp);
854891
}
855892
};

0 commit comments

Comments
 (0)