Skip to content

Commit f6a5b7d

Browse files
authored
[PWGHF] candidateCreator3Prong: refine logic of KF reconstruction (#18538)
1 parent 0b069a5 commit f6a5b7d

1 file changed

Lines changed: 92 additions & 62 deletions

File tree

‎PWGHF/TableProducer/candidateCreator3Prong.cxx‎

Lines changed: 92 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ struct HfCandidateCreator3Prong {
143143
// KF
144144
Configurable<bool> applyTopoConstraint{"applyTopoConstraint", false, "apply origin from PV hypothesis for created candidate, works only in KF mode"};
145145
Configurable<bool> applyInvMassConstraint{"applyInvMassConstraint", false, "apply particle type hypothesis to recalculate created candidate's momentum, works only in KF mode"};
146+
Configurable<bool> kfConstructWithEnergyFitMc{"kfConstructWithEnergyFitMc", true, "for details see https://github.com/alisw/KFParticle/blob/a00323cd7b022430abcb3c43f18188b291b0c803/KFParticle/KFParticleBase.cxx#L625"};
146147

147148
Configurable<LabeledArray<float>> tpcPidBBParamsLightNuclei{"tpcPidBBParamsLightNuclei", {hf_presel_lightnuclei::BetheBlochParams[0], hf_presel_lightnuclei::NParticleRows, hf_presel_lightnuclei::NBetheBlochParams, hf_presel_lightnuclei::labelsRowsNucleiType, hf_presel_lightnuclei::labelsBetheBlochParams}, "TPC PID Bethe–Bloch parameter configurations for light nuclei (deuteron, triton, helium-3, alpha)"};
148149

@@ -169,19 +170,22 @@ struct HfCandidateCreator3Prong {
169170

170171
void init(InitContext const&)
171172
{
172-
std::array<bool, 8> doprocessDF{doprocessPvRefitWithDCAFitterN, doprocessNoPvRefitWithDCAFitterN,
173-
doprocessPvRefitWithDCAFitterNCentFT0C, doprocessNoPvRefitWithDCAFitterNCentFT0C,
174-
doprocessPvRefitWithDCAFitterNCentFT0M, doprocessNoPvRefitWithDCAFitterNCentFT0M, doprocessPvRefitWithDCAFitterNUpc, doprocessNoPvRefitWithDCAFitterNUpc};
175-
std::array<bool, 8> doprocessKF{doprocessPvRefitWithKFParticle, doprocessNoPvRefitWithKFParticle,
176-
doprocessPvRefitWithKFParticleCentFT0C, doprocessNoPvRefitWithKFParticleCentFT0C,
177-
doprocessPvRefitWithKFParticleCentFT0M, doprocessNoPvRefitWithKFParticleCentFT0M, doprocessPvRefitWithKFParticleUpc, doprocessNoPvRefitWithKFParticleUpc};
173+
const std::array<bool, 8> doprocessDF{doprocessPvRefitWithDCAFitterN, doprocessNoPvRefitWithDCAFitterN,
174+
doprocessPvRefitWithDCAFitterNCentFT0C, doprocessNoPvRefitWithDCAFitterNCentFT0C,
175+
doprocessPvRefitWithDCAFitterNCentFT0M, doprocessNoPvRefitWithDCAFitterNCentFT0M, doprocessPvRefitWithDCAFitterNUpc, doprocessNoPvRefitWithDCAFitterNUpc};
176+
const std::array<bool, 8> doprocessKF{doprocessPvRefitWithKFParticle, doprocessNoPvRefitWithKFParticle,
177+
doprocessPvRefitWithKFParticleCentFT0C, doprocessNoPvRefitWithKFParticleCentFT0C,
178+
doprocessPvRefitWithKFParticleCentFT0M, doprocessNoPvRefitWithKFParticleCentFT0M, doprocessPvRefitWithKFParticleUpc, doprocessNoPvRefitWithKFParticleUpc};
178179
if ((std::accumulate(doprocessDF.begin(), doprocessDF.end(), 0) + std::accumulate(doprocessKF.begin(), doprocessKF.end(), 0)) != 1) {
179180
LOGP(fatal, "One and only one process function must be enabled at a time.");
180181
}
181-
std::array<bool, 4> processesCollisions = {doprocessCollisions, doprocessCollisionsCentFT0C, doprocessCollisionsCentFT0M, doprocessCollisionsUpc};
182+
if (std::accumulate(doprocessKF.begin(), doprocessKF.end(), 0) == 1 && createCharmNuclei == true) {
183+
LOGP(fatal, "KF based reconstruction of charm nuclei is not impemented yet.");
184+
}
185+
const std::array<bool, 4> processesCollisions = {doprocessCollisions, doprocessCollisionsCentFT0C, doprocessCollisionsCentFT0M, doprocessCollisionsUpc};
182186
const int nProcessesCollisions = std::accumulate(processesCollisions.begin(), processesCollisions.end(), 0);
183187

184-
std::array<bool, 5> processesUpc = {doprocessPvRefitWithDCAFitterNUpc, doprocessNoPvRefitWithDCAFitterNUpc, doprocessPvRefitWithKFParticleUpc, doprocessNoPvRefitWithKFParticleUpc, doprocessCollisionsUpc};
188+
const std::array<bool, 5> processesUpc = {doprocessPvRefitWithDCAFitterNUpc, doprocessNoPvRefitWithDCAFitterNUpc, doprocessPvRefitWithKFParticleUpc, doprocessNoPvRefitWithKFParticleUpc, doprocessCollisionsUpc};
185189
const int nProcessesUpc = std::accumulate(processesUpc.begin(), processesUpc.end(), 0);
186190

187191
if (nProcessesCollisions > 1) {
@@ -204,13 +208,13 @@ struct HfCandidateCreator3Prong {
204208
if (nProcessesUpc > 0 && isRun2) {
205209
LOGP(fatal, "Process function for UPC is only available in Run 3!");
206210
}
207-
std::array<bool, 5> creationFlags = {createDplus, createDs, createLc, createXic, createCharmNuclei};
208-
if (std::accumulate(creationFlags.begin(), creationFlags.end(), 0) == 0) {
211+
const std::array<bool, 5> creationFlags = {createDplus, createDs, createLc, createXic, createCharmNuclei};
212+
const int nParticlesToCreate = std::accumulate(creationFlags.begin(), creationFlags.end(), 0);
213+
if (nParticlesToCreate == 0) {
209214
LOGP(fatal, "At least one particle specie should be enabled for the creation.");
210215
}
211-
212-
if (createLc && createXic && applyInvMassConstraint) {
213-
LOGP(fatal, "Unable to apply invariant mass constraint due to ambiguity of mass hypothesis: only one of Lc and Xic and Cd can be reconstructed.");
216+
if (nParticlesToCreate > 1 && applyInvMassConstraint) {
217+
LOGP(fatal, "Invariant mass constraint can be applied only when one particle specie is requested for creation.");
214218
}
215219

216220
// histograms
@@ -472,9 +476,11 @@ struct HfCandidateCreator3Prong {
472476
TracksWCovExtraPidPiKaPrLightNuclei const&,
473477
BCsType const& bcs)
474478
{
479+
const int kfConstructMethod = kfConstructWithEnergyFitMc ? 2 : 0;
480+
475481
for (const auto& rowTrackIndexProng3 : rowsTrackIndexProng3) {
476482
/// reject candidates in collisions not satisfying the event selections
477-
auto collision = rowTrackIndexProng3.template collision_as<Coll>();
483+
const auto collision = rowTrackIndexProng3.template collision_as<Coll>();
478484
float centrality{-1.f};
479485
o2::hf_evsel::HfCollisionRejectionMask rejectionMask{};
480486
if constexpr (ApplyUpcSel) {
@@ -487,14 +493,14 @@ struct HfCandidateCreator3Prong {
487493
continue;
488494
}
489495

490-
auto track0 = rowTrackIndexProng3.template prong0_as<TracksWCovExtraPidPiKaPrLightNuclei>();
491-
auto track1 = rowTrackIndexProng3.template prong1_as<TracksWCovExtraPidPiKaPrLightNuclei>();
492-
auto track2 = rowTrackIndexProng3.template prong2_as<TracksWCovExtraPidPiKaPrLightNuclei>();
496+
const auto track0 = rowTrackIndexProng3.template prong0_as<TracksWCovExtraPidPiKaPrLightNuclei>();
497+
const auto track1 = rowTrackIndexProng3.template prong1_as<TracksWCovExtraPidPiKaPrLightNuclei>();
498+
const auto track2 = rowTrackIndexProng3.template prong2_as<TracksWCovExtraPidPiKaPrLightNuclei>();
493499

494500
/// Set the magnetic field from ccdb.
495501
/// The static instance of the propagator was already modified in the HFTrackIndexSkimCreator,
496502
/// but this is not true when running on Run2 data/MC already converted into AO2Ds.
497-
auto bc = collision.template bc_as<aod::BCsWithTimestamps>();
503+
const auto bc = collision.template bc_as<aod::BCsWithTimestamps>();
498504
if (runNumber != bc.runNumber()) {
499505
LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber;
500506
initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, nullptr, isRun2);
@@ -517,7 +523,7 @@ struct HfCandidateCreator3Prong {
517523
kfpVertex.SetCovarianceMatrix(rowTrackIndexProng3.pvRefitSigmaX2(), rowTrackIndexProng3.pvRefitSigmaXY(), rowTrackIndexProng3.pvRefitSigmaY2(), rowTrackIndexProng3.pvRefitSigmaXZ(), rowTrackIndexProng3.pvRefitSigmaYZ(), rowTrackIndexProng3.pvRefitSigmaZ2());
518524
}
519525
kfpVertex.GetCovarianceMatrix(covMatrixPV);
520-
KFParticle kfpV(kfpVertex);
526+
const KFParticle kfpV(kfpVertex);
521527
registry.fill(HIST("hCovPVXX"), covMatrixPV[0]);
522528
registry.fill(HIST("hCovPVYY"), covMatrixPV[2]);
523529
registry.fill(HIST("hCovPVXZ"), covMatrixPV[3]);
@@ -558,9 +564,9 @@ struct HfCandidateCreator3Prong {
558564
registry.fill(HIST("hDcaZProngs"), track2.pt(), UndefValueFloat);
559565
}
560566

561-
auto [impactParameter0Z, errImpactParameter0Z] = kfCalculateImpactParameterZ(kfFirstProton, kfpV);
562-
auto [impactParameter1Z, errImpactParameter1Z] = kfCalculateImpactParameterZ(kfSecondKaon, kfpV);
563-
auto [impactParameter2Z, errImpactParameter2Z] = kfCalculateImpactParameterZ(kfThirdProton, kfpV);
567+
const auto [impactParameter0Z, errImpactParameter0Z] = kfCalculateImpactParameterZ(kfFirstProton, kfpV);
568+
const auto [impactParameter1Z, errImpactParameter1Z] = kfCalculateImpactParameterZ(kfSecondKaon, kfpV);
569+
const auto [impactParameter2Z, errImpactParameter2Z] = kfCalculateImpactParameterZ(kfThirdProton, kfpV);
564570

565571
const float chi2primFirst = kfCalculateChi2ToPrimaryVertex(kfFirstProton, kfpV);
566572
const float chi2primSecond = kfCalculateChi2ToPrimaryVertex(kfSecondKaon, kfpV);
@@ -574,33 +580,53 @@ struct HfCandidateCreator3Prong {
574580
const float chi2geoFirstThird = kfCalculateChi2geoBetweenParticles(kfFirstProton, kfThirdPion);
575581
const float chi2geoFirstSecond = kfCalculateChi2geoBetweenParticles(kfFirstProton, kfSecondKaon);
576582

583+
KFParticle* kfCandGeneric{nullptr};
584+
577585
// Λc± → p± K∓ π±, Ξc± → p± K∓ π±
578586
KFParticle kfCandPKPi;
579587
const KFParticle* kfDaughtersPKPi[3] = {&kfFirstProton, &kfSecondKaon, &kfThirdPion};
580-
kfCandPKPi.SetConstructMethod(2);
581-
kfCandPKPi.Construct(kfDaughtersPKPi, 3);
588+
kfCandPKPi.SetConstructMethod(kfConstructMethod);
582589
KFParticle kfCandPiKP;
583590
const KFParticle* kfDaughtersPiKP[3] = {&kfFirstPion, &kfSecondKaon, &kfThirdProton};
584-
kfCandPiKP.SetConstructMethod(2);
585-
kfCandPiKP.Construct(kfDaughtersPiKP, 3);
591+
kfCandPiKP.SetConstructMethod(kfConstructMethod);
592+
if (createLc || createXic) {
593+
kfCandPKPi.Construct(kfDaughtersPKPi, 3);
594+
kfCandPiKP.Construct(kfDaughtersPiKP, 3);
595+
kfCandGeneric = &kfCandPKPi;
596+
}
586597

587598
// D± → π± K∓ π±
588599
KFParticle kfCandPiKPi;
589600
const KFParticle* kfDaughtersPiKPi[3] = {&kfFirstPion, &kfSecondKaon, &kfThirdPion};
590-
kfCandPiKPi.SetConstructMethod(2);
591-
kfCandPiKPi.Construct(kfDaughtersPiKPi, 3);
601+
kfCandPiKPi.SetConstructMethod(kfConstructMethod);
602+
if (createDplus) {
603+
kfCandPiKPi.Construct(kfDaughtersPiKPi, 3);
604+
if (kfCandGeneric == nullptr) {
605+
kfCandGeneric = &kfCandPiKPi;
606+
}
607+
}
592608

593609
// Ds± → K± K∓ π±
594610
KFParticle kfCandKKPi;
595611
const KFParticle* kfDaughtersKKPi[3] = {&kfFirstKaon, &kfSecondKaon, &kfThirdPion};
596-
kfCandKKPi.SetConstructMethod(2);
597-
kfCandKKPi.Construct(kfDaughtersKKPi, 3);
612+
kfCandKKPi.SetConstructMethod(kfConstructMethod);
598613
KFParticle kfCandPiKK;
599614
const KFParticle* kfDaughtersPiKK[3] = {&kfFirstPion, &kfSecondKaon, &kfThirdKaon};
600-
kfCandPiKK.SetConstructMethod(2);
601-
kfCandPiKK.Construct(kfDaughtersPiKK, 3);
615+
kfCandPiKK.SetConstructMethod(kfConstructMethod);
616+
if (createDs) {
617+
kfCandKKPi.Construct(kfDaughtersKKPi, 3);
618+
kfCandPiKK.Construct(kfDaughtersPiKK, 3);
619+
if (kfCandGeneric == nullptr) {
620+
kfCandGeneric = &kfCandKKPi;
621+
}
622+
}
602623

603-
const float chi2topo = kfCalculateChi2ToPrimaryVertex(kfCandPKPi, kfpV);
624+
if (kfCandGeneric == nullptr) {
625+
// should never happen, but for redundant safety
626+
LOGP(fatal, "kfCandGeneric was not assigned with address of any candidate hypothesis. Check the create<...> configurables");
627+
}
628+
629+
const float chi2topo = kfCalculateChi2ToPrimaryVertex(*kfCandGeneric, kfpV);
604630

605631
if (applyTopoConstraint) { // constraints applied after chi2topo getter - to preserve unbiased value of chi2topo
606632
for (const auto& kfCand : std::array<KFParticle*, 5>{&kfCandPKPi, &kfCandPiKP, &kfCandPiKPi, &kfCandKKPi, &kfCandPiKK}) {
@@ -610,13 +636,13 @@ struct HfCandidateCreator3Prong {
610636
}
611637

612638
KFParticle kfPairKPi;
613-
const KFParticle* kfDaughtersKPi[3] = {&kfSecondKaon, &kfThirdPion};
614-
kfPairKPi.SetConstructMethod(2);
639+
const KFParticle* kfDaughtersKPi[2] = {&kfSecondKaon, &kfThirdPion};
640+
kfPairKPi.SetConstructMethod(kfConstructMethod);
615641
kfPairKPi.Construct(kfDaughtersKPi, 2);
616642

617643
KFParticle kfPairPiK;
618-
const KFParticle* kfDaughtersPiK[3] = {&kfFirstPion, &kfSecondKaon};
619-
kfPairPiK.SetConstructMethod(2);
644+
const KFParticle* kfDaughtersPiK[2] = {&kfFirstPion, &kfSecondKaon};
645+
kfPairPiK.SetConstructMethod(kfConstructMethod);
620646
kfPairPiK.Construct(kfDaughtersPiK, 2);
621647

622648
const float massPKPi = kfCandPKPi.GetMass();
@@ -628,32 +654,36 @@ struct HfCandidateCreator3Prong {
628654
const float massPiK = kfPairPiK.GetMass();
629655

630656
if (applyInvMassConstraint) { // constraints applied after minv getters - to preserve unbiased values of minv
631-
kfCandPKPi.SetNonlinearMassConstraint(createLc ? static_cast<float>(MassLambdaCPlus) : static_cast<float>(MassXiCPlus));
632-
kfCandPiKP.SetNonlinearMassConstraint(createLc ? static_cast<float>(MassLambdaCPlus) : static_cast<float>(MassXiCPlus));
633-
kfCandPiKPi.SetNonlinearMassConstraint(static_cast<float>(MassDPlus));
634-
kfCandKKPi.SetNonlinearMassConstraint(static_cast<float>(MassDS));
635-
kfCandPiKK.SetNonlinearMassConstraint(static_cast<float>(MassDS));
657+
if (createLc) {
658+
kfCandGeneric->SetNonlinearMassConstraint(MassLambdaCPlus);
659+
} else if (createXic) {
660+
kfCandGeneric->SetNonlinearMassConstraint(MassXiCPlus);
661+
} else if (createDplus) {
662+
kfCandGeneric->SetNonlinearMassConstraint(MassDPlus);
663+
} else if (createDs) {
664+
kfCandGeneric->SetNonlinearMassConstraint(MassDS);
665+
}
636666
}
637667

638-
const float chi2geo = kfCandPKPi.Chi2() / static_cast<float>(kfCandPKPi.NDF());
639-
const std::pair<float, float> ldl = kfCalculateLdL(kfCandPKPi, kfpV);
668+
const float chi2geo = kfCandGeneric->Chi2() / static_cast<float>(kfCandGeneric->NDF());
669+
const std::pair<float, float> ldl = kfCalculateLdL(*kfCandGeneric, kfpV);
640670

641-
std::array<float, 3> pProng0 = kfCalculateProngMomentumInSecondaryVertex(kfFirstProton, kfCandPiKP);
642-
std::array<float, 3> pProng1 = kfCalculateProngMomentumInSecondaryVertex(kfSecondKaon, kfCandPiKP);
643-
std::array<float, 3> pProng2 = kfCalculateProngMomentumInSecondaryVertex(kfThirdPion, kfCandPiKP);
671+
const std::array<float, 3> pProng0 = kfCalculateProngMomentumInSecondaryVertex(kfFirstProton, *kfCandGeneric);
672+
const std::array<float, 3> pProng1 = kfCalculateProngMomentumInSecondaryVertex(kfSecondKaon, *kfCandGeneric);
673+
const std::array<float, 3> pProng2 = kfCalculateProngMomentumInSecondaryVertex(kfThirdPion, *kfCandGeneric);
644674

645-
registry.fill(HIST("hCovSVXX"), kfCandPKPi.Covariance(0, 0));
646-
registry.fill(HIST("hCovSVYY"), kfCandPKPi.Covariance(1, 1));
647-
registry.fill(HIST("hCovSVXZ"), kfCandPKPi.Covariance(2, 0));
648-
registry.fill(HIST("hCovSVZZ"), kfCandPKPi.Covariance(2, 2));
675+
registry.fill(HIST("hCovSVXX"), kfCandGeneric->GetCovariance(0, 0));
676+
registry.fill(HIST("hCovSVYY"), kfCandGeneric->GetCovariance(1, 1));
677+
registry.fill(HIST("hCovSVXZ"), kfCandGeneric->GetCovariance(2, 0));
678+
registry.fill(HIST("hCovSVZZ"), kfCandGeneric->GetCovariance(2, 2));
649679

650-
auto* covMatrixSV = kfCandPKPi.CovarianceMatrix();
680+
const auto* const covMatrixSV = kfCandGeneric->CovarianceMatrix();
651681
double phi{}, theta{};
652-
getPointDirection(std::array{kfpV.GetX(), kfpV.GetY(), kfpV.GetZ()}, std::array{kfCandPKPi.GetX(), kfCandPKPi.GetY(), kfCandPKPi.GetZ()}, phi, theta);
653-
auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixSV, phi, theta));
654-
auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixSV, phi, 0.));
682+
getPointDirection(std::array{kfpV.GetX(), kfpV.GetY(), kfpV.GetZ()}, std::array{kfCandGeneric->GetX(), kfCandGeneric->GetY(), kfCandGeneric->GetZ()}, phi, theta);
683+
const auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixSV, phi, theta));
684+
const auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixSV, phi, 0.));
655685

656-
auto indexCollision = collision.globalIndex();
686+
const auto indexCollision = collision.globalIndex();
657687
uint8_t bitmapProngsContributorsPV = 0;
658688
if (indexCollision == track0.collisionId() && track0.isPVContributor()) {
659689
SETBIT(bitmapProngsContributorsPV, 0);
@@ -669,9 +699,9 @@ struct HfCandidateCreator3Prong {
669699
// fill candidate table rows
670700
rowCandidateBase(indexCollision,
671701
kfpV.GetX(), kfpV.GetY(), kfpV.GetZ(),
672-
kfCandPKPi.GetX(), kfCandPKPi.GetY(), kfCandPKPi.GetZ(),
702+
kfCandGeneric->GetX(), kfCandGeneric->GetY(), kfCandGeneric->GetZ(),
673703
errorDecayLength, errorDecayLengthXY,
674-
kfCandPKPi.GetChi2() / static_cast<float>(kfCandPKPi.GetNDF()),
704+
kfCandGeneric->GetChi2() / static_cast<float>(kfCandGeneric->GetNDF()),
675705
pProng0.at(0), pProng0.at(1), pProng0.at(2),
676706
pProng1.at(0), pProng1.at(1), pProng1.at(2),
677707
pProng2.at(0), pProng2.at(1), pProng2.at(2),
@@ -683,11 +713,11 @@ struct HfCandidateCreator3Prong {
683713
rowTrackIndexProng3.hfflag());
684714

685715
// fill KF info
686-
rowCandidateKF(kfCandPKPi.GetErrX(), kfCandPKPi.GetErrY(), kfCandPKPi.GetErrZ(),
687-
std::sqrt(kfpV.Covariance(0, 0)), std::sqrt(kfpV.Covariance(1, 1)), std::sqrt(kfpV.Covariance(2, 2)),
716+
rowCandidateKF(kfCandGeneric->GetErrX(), kfCandGeneric->GetErrY(), kfCandGeneric->GetErrZ(),
717+
std::sqrt(kfpV.GetCovariance(0, 0)), std::sqrt(kfpV.GetCovariance(1, 1)), std::sqrt(kfpV.GetCovariance(2, 2)),
688718
massPKPi, massPiKP, massPiKPi, massKKPi, massPiKK, massKPi, massPiK,
689-
kfCandPKPi.GetPx(), kfCandPKPi.GetPy(), kfCandPKPi.GetPz(),
690-
kfCandPKPi.GetErrPx(), kfCandPKPi.GetErrPy(), kfCandPKPi.GetErrPz(),
719+
kfCandGeneric->GetPx(), kfCandGeneric->GetPy(), kfCandGeneric->GetPz(),
720+
kfCandGeneric->GetErrPx(), kfCandGeneric->GetErrPy(), kfCandGeneric->GetErrPz(),
691721
chi2primFirst, chi2primSecond, chi2primThird,
692722
dcaSecondThird, dcaFirstThird, dcaFirstSecond,
693723
chi2geoSecondThird, chi2geoFirstThird, chi2geoFirstSecond,

0 commit comments

Comments
 (0)