Skip to content

Commit eb33730

Browse files
authored
[PWGHF] Add proper lifetime into THnSparse at taskLc (#12902)
1 parent deb7708 commit eb33730

File tree

1 file changed

+108
-62
lines changed

1 file changed

+108
-62
lines changed

PWGHF/D2H/Tasks/taskLc.cxx

Lines changed: 108 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@ struct HfTaskLc {
6565
Configurable<bool> fillTHn{"fillTHn", false, "fill THn"};
6666
Configurable<bool> storeOccupancy{"storeOccupancy", true, "Flag to store occupancy information"};
6767
Configurable<int> occEstimator{"occEstimator", 2, "Occupancy estimation (None: 0, ITS: 1, FT0C: 2)"};
68+
Configurable<bool> storeProperLifetime{"storeProperLifetime", false, "Flag to store proper lifetime"};
69+
70+
constexpr static float CtToProperLifetimePs = 1.f / o2::constants::physics::LightSpeedCm2PS;
71+
constexpr static float NanoToPico = 1000.f;
72+
73+
enum MlClasses : int {
74+
MlClassBackground = 0,
75+
MlClassPrompt,
76+
MlClassNonPrompt,
77+
NumberOfMlClasses
78+
};
6879

6980
HfHelper hfHelper;
7081
SliceCache cache;
@@ -100,6 +111,7 @@ struct HfTaskLc {
100111
ConfigurableAxis thnConfigAxisGenPtB{"thnConfigAxisGenPtB", {1000, 0, 100}, "Gen Pt B"};
101112
ConfigurableAxis thnConfigAxisNumPvContr{"thnConfigAxisNumPvContr", {200, -0.5, 199.5}, "Number of PV contributors"};
102113
ConfigurableAxis thnConfigAxisOccupancy{"thnConfigAxisOccupancy", {14, 0, 14000}, "axis for centrality"};
114+
ConfigurableAxis thnConfigAxisProperLifetime{"thnConfigAxisProperLifetime", {200, 0, 2}, "Proper lifetime, ps"};
103115

104116
HistogramRegistry registry{
105117
"registry",
@@ -317,6 +329,7 @@ struct HfTaskLc {
317329
const AxisSpec thnAxisPtB{thnConfigAxisGenPtB, "#it{p}_{T}^{B} (GeV/#it{c})"};
318330
const AxisSpec thnAxisTracklets{thnConfigAxisNumPvContr, "Number of PV contributors"};
319331
const AxisSpec thnAxisOccupancy{thnConfigAxisOccupancy, "Occupancy"};
332+
const AxisSpec thnAxisProperLifetime{thnConfigAxisProperLifetime, "T_{proper} (ps)"};
320333

321334
bool isDataWithMl = doprocessDataWithMl || doprocessDataWithMlWithFT0C || doprocessDataWithMlWithFT0M;
322335
bool isMcWithMl = doprocessMcWithMl || doprocessMcWithMlWithFT0C || doprocessMcWithMlWithFT0M;
@@ -342,12 +355,18 @@ struct HfTaskLc {
342355
}
343356

344357
if (storeOccupancy) {
345-
if (!axesWithBdt.empty())
346-
axesWithBdt.push_back(thnAxisOccupancy);
347-
if (!axesStd.empty())
348-
axesStd.push_back(thnAxisOccupancy);
349-
if (!axesGen.empty())
350-
axesGen.push_back(thnAxisOccupancy);
358+
for (const auto& axes : std::array<std::vector<AxisSpec>*, 3>{&axesWithBdt, &axesStd, &axesGen}) {
359+
if (!axes->empty()) {
360+
axes->push_back(thnAxisOccupancy);
361+
}
362+
}
363+
}
364+
if (storeProperLifetime) {
365+
for (const auto& axes : std::array<std::vector<AxisSpec>*, 3>{&axesWithBdt, &axesStd, &axesGen}) {
366+
if (!axes->empty()) {
367+
axes->push_back(thnAxisProperLifetime);
368+
}
369+
}
351370
}
352371

353372
if (isDataWithMl) {
@@ -542,55 +561,63 @@ struct HfTaskLc {
542561
}
543562
double massLc(-1);
544563
double outputBkg(-1), outputPrompt(-1), outputFD(-1);
564+
const float properLifetime = hfHelper.ctLc(candidate) * CtToProperLifetimePs;
545565
if ((candidate.isSelLcToPKPi() >= selectionFlagLc) && pdgCodeProng0 == kProton) {
546566
massLc = hfHelper.invMassLcToPKPi(candidate);
547567

548568
if constexpr (fillMl) {
549-
if (candidate.mlProbLcToPKPi().size() == 3) {
550-
outputBkg = candidate.mlProbLcToPKPi()[0]; /// bkg score
551-
outputPrompt = candidate.mlProbLcToPKPi()[1]; /// prompt score
552-
outputFD = candidate.mlProbLcToPKPi()[2]; /// non-prompt score
569+
if (candidate.mlProbLcToPKPi().size() == NumberOfMlClasses) {
570+
outputBkg = candidate.mlProbLcToPKPi()[MlClassBackground]; /// bkg score
571+
outputPrompt = candidate.mlProbLcToPKPi()[MlClassPrompt]; /// prompt score
572+
outputFD = candidate.mlProbLcToPKPi()[MlClassNonPrompt]; /// non-prompt score
553573
}
554574
/// Fill the ML outputScores and variables of candidate
575+
std::vector<double> valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast<double>(numPvContributors), ptRecB, static_cast<double>(originType)};
555576
if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
556-
registry.get<THnSparse>(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType, occ);
557-
} else {
558-
registry.get<THnSparse>(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType);
577+
valuesToFill.push_back(occ);
559578
}
560-
579+
if (storeProperLifetime) {
580+
valuesToFill.push_back(properLifetime);
581+
}
582+
registry.get<THnSparse>(HIST("hnLcVarsWithBdt"))->Fill(valuesToFill.data());
561583
} else {
562-
584+
std::vector<double> valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast<double>(numPvContributors), ptRecB, static_cast<double>(originType)};
563585
if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
564-
registry.get<THnSparse>(HIST("hnLcVars"))->Fill(massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, ptRecB, originType, occ);
565-
566-
} else {
567-
568-
registry.get<THnSparse>(HIST("hnLcVars"))->Fill(massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, ptRecB, originType);
586+
valuesToFill.push_back(occ);
587+
}
588+
if (storeProperLifetime) {
589+
valuesToFill.push_back(properLifetime);
569590
}
591+
registry.get<THnSparse>(HIST("hnLcVars"))->Fill(valuesToFill.data());
570592
}
571593
}
572594
if ((candidate.isSelLcToPiKP() >= selectionFlagLc) && pdgCodeProng0 == kPiPlus) {
573595
massLc = hfHelper.invMassLcToPiKP(candidate);
574596

575597
if constexpr (fillMl) {
576-
if (candidate.mlProbLcToPiKP().size() == 3) {
577-
outputBkg = candidate.mlProbLcToPiKP()[0]; /// bkg score
578-
outputPrompt = candidate.mlProbLcToPiKP()[1]; /// prompt score
579-
outputFD = candidate.mlProbLcToPiKP()[2]; /// non-prompt score
598+
if (candidate.mlProbLcToPiKP().size() == NumberOfMlClasses) {
599+
outputBkg = candidate.mlProbLcToPiKP()[MlClassBackground]; /// bkg score
600+
outputPrompt = candidate.mlProbLcToPiKP()[MlClassPrompt]; /// prompt score
601+
outputFD = candidate.mlProbLcToPiKP()[MlClassNonPrompt]; /// non-prompt score
580602
}
581603
/// Fill the ML outputScores and variables of candidate (todo: add multiplicity)
604+
std::vector<double> valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast<double>(numPvContributors), ptRecB, static_cast<double>(originType)};
582605
if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
583-
registry.get<THnSparse>(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType, occ);
584-
585-
} else {
586-
registry.get<THnSparse>(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, ptRecB, originType);
606+
valuesToFill.push_back(occ);
607+
}
608+
if (storeProperLifetime) {
609+
valuesToFill.push_back(properLifetime);
587610
}
611+
registry.get<THnSparse>(HIST("hnLcVarsWithBdt"))->Fill(valuesToFill.data());
588612
} else {
613+
std::vector<double> valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast<double>(numPvContributors), ptRecB, static_cast<double>(originType)};
589614
if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
590-
registry.get<THnSparse>(HIST("hnLcVars"))->Fill(massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, ptRecB, originType, occ);
591-
} else {
592-
registry.get<THnSparse>(HIST("hnLcVars"))->Fill(massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, ptRecB, originType);
615+
valuesToFill.push_back(occ);
593616
}
617+
if (storeProperLifetime) {
618+
valuesToFill.push_back(properLifetime);
619+
}
620+
registry.get<THnSparse>(HIST("hnLcVars"))->Fill(valuesToFill.data());
594621
}
595622
}
596623
}
@@ -624,6 +651,11 @@ struct HfTaskLc {
624651
occ = o2::hf_occupancy::getOccupancyGenColl(recoCollsPerMcColl, occEstimator);
625652
}
626653

654+
const auto mcDaughter0 = particle.template daughters_as<soa::Join<aod::McParticles, aod::HfCand3ProngMcGen>>().begin();
655+
const float p2m = particle.p() / o2::constants::physics::MassLambdaCPlus;
656+
const float gamma = std::sqrt(1 + p2m * p2m); // mother's particle Lorentz factor
657+
const float properLifetime = mcDaughter0.vt() * NanoToPico / gamma; // from ns to ps * from lab time to proper time
658+
627659
registry.fill(HIST("MC/generated/signal/hPtGen"), ptGen);
628660
registry.fill(HIST("MC/generated/signal/hEtaGen"), particle.eta());
629661
registry.fill(HIST("MC/generated/signal/hYGen"), yGen);
@@ -634,12 +666,14 @@ struct HfTaskLc {
634666

635667
if (particle.originMcGen() == RecoDecay::OriginType::Prompt) {
636668
if (fillTHn) {
669+
std::vector<double> valuesToFill{ptGen, cent, yGen, static_cast<double>(numPvContributors), ptGenB, static_cast<double>(originType)};
637670
if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
638-
registry.get<THnSparse>(HIST("hnLcVarsGen"))->Fill(ptGen, cent, yGen, numPvContributors, ptGenB, originType, occ);
639-
640-
} else {
641-
registry.get<THnSparse>(HIST("hnLcVarsGen"))->Fill(ptGen, cent, yGen, numPvContributors, ptGenB, originType);
671+
valuesToFill.push_back(occ);
672+
}
673+
if (storeProperLifetime) {
674+
valuesToFill.push_back(properLifetime);
642675
}
676+
registry.get<THnSparse>(HIST("hnLcVarsGen"))->Fill(valuesToFill.data());
643677
}
644678
registry.fill(HIST("MC/generated/prompt/hPtGenPrompt"), ptGen);
645679
registry.fill(HIST("MC/generated/prompt/hEtaGenPrompt"), particle.eta());
@@ -652,12 +686,14 @@ struct HfTaskLc {
652686
if (particle.originMcGen() == RecoDecay::OriginType::NonPrompt) {
653687
ptGenB = mcParticles.rawIteratorAt(particle.idxBhadMotherPart()).pt();
654688
if (fillTHn) {
689+
std::vector<double> valuesToFill{ptGen, cent, yGen, static_cast<double>(numPvContributors), ptGenB, static_cast<double>(originType)};
655690
if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
656-
registry.get<THnSparse>(HIST("hnLcVarsGen"))->Fill(ptGen, cent, yGen, numPvContributors, ptGenB, originType, occ);
657-
658-
} else {
659-
registry.get<THnSparse>(HIST("hnLcVarsGen"))->Fill(ptGen, cent, yGen, numPvContributors, ptGenB, originType);
691+
valuesToFill.push_back(occ);
660692
}
693+
if (storeProperLifetime) {
694+
valuesToFill.push_back(properLifetime);
695+
}
696+
registry.get<THnSparse>(HIST("hnLcVarsGen"))->Fill(valuesToFill.data());
661697
}
662698
registry.fill(HIST("MC/generated/nonprompt/hPtGenNonPrompt"), ptGen);
663699
registry.fill(HIST("MC/generated/nonprompt/hEtaGenNonPrompt"), particle.eta());
@@ -748,53 +784,63 @@ struct HfTaskLc {
748784
}
749785
double massLc(-1);
750786
double outputBkg(-1), outputPrompt(-1), outputFD(-1);
787+
const float properLifetime = hfHelper.ctLc(candidate) * CtToProperLifetimePs;
751788
if (candidate.isSelLcToPKPi() >= selectionFlagLc) {
752789
massLc = hfHelper.invMassLcToPKPi(candidate);
753790

754791
if constexpr (fillMl) {
755-
if (candidate.mlProbLcToPKPi().size() == 3) {
756-
outputBkg = candidate.mlProbLcToPKPi()[0]; /// bkg score
757-
outputPrompt = candidate.mlProbLcToPKPi()[1]; /// prompt score
758-
outputFD = candidate.mlProbLcToPKPi()[2]; /// non-prompt score
792+
if (candidate.mlProbLcToPKPi().size() == NumberOfMlClasses) {
793+
outputBkg = candidate.mlProbLcToPKPi()[MlClassBackground]; /// bkg score
794+
outputPrompt = candidate.mlProbLcToPKPi()[MlClassPrompt]; /// prompt score
795+
outputFD = candidate.mlProbLcToPKPi()[MlClassNonPrompt]; /// non-prompt score
759796
}
760797
/// Fill the ML outputScores and variables of candidate
798+
std::vector<double> valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast<double>(numPvContributors)};
761799
if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
762-
registry.get<THnSparse>(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, occ);
763-
764-
} else {
765-
registry.get<THnSparse>(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors);
800+
valuesToFill.push_back(occ);
801+
}
802+
if (storeProperLifetime) {
803+
valuesToFill.push_back(properLifetime);
766804
}
805+
registry.get<THnSparse>(HIST("hnLcVarsWithBdt"))->Fill(valuesToFill.data());
767806
} else {
807+
std::vector<double> valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast<double>(numPvContributors)};
768808
if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
769-
770-
registry.get<THnSparse>(HIST("hnLcVars"))->Fill(massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, occ);
771-
} else {
772-
773-
registry.get<THnSparse>(HIST("hnLcVars"))->Fill(massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors);
809+
valuesToFill.push_back(occ);
810+
}
811+
if (storeProperLifetime) {
812+
valuesToFill.push_back(properLifetime);
774813
}
814+
registry.get<THnSparse>(HIST("hnLcVars"))->Fill(valuesToFill.data());
775815
}
776816
}
777817
if (candidate.isSelLcToPiKP() >= selectionFlagLc) {
778818
massLc = hfHelper.invMassLcToPiKP(candidate);
779819

780820
if constexpr (fillMl) {
781-
if (candidate.mlProbLcToPiKP().size() == 3) {
782-
outputBkg = candidate.mlProbLcToPiKP()[0]; /// bkg score
783-
outputPrompt = candidate.mlProbLcToPiKP()[1]; /// prompt score
784-
outputFD = candidate.mlProbLcToPiKP()[2]; /// non-prompt score
821+
if (candidate.mlProbLcToPiKP().size() == NumberOfMlClasses) {
822+
outputBkg = candidate.mlProbLcToPiKP()[MlClassBackground]; /// bkg score
823+
outputPrompt = candidate.mlProbLcToPiKP()[MlClassPrompt]; /// prompt score
824+
outputFD = candidate.mlProbLcToPiKP()[MlClassNonPrompt]; /// non-prompt score
785825
}
786826
/// Fill the ML outputScores and variables of candidate
827+
std::vector<double> valuesToFill{massLc, pt, cent, outputBkg, outputPrompt, outputFD, static_cast<double>(numPvContributors)};
787828
if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
788-
registry.get<THnSparse>(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors, occ);
789-
} else {
790-
registry.get<THnSparse>(HIST("hnLcVarsWithBdt"))->Fill(massLc, pt, cent, outputBkg, outputPrompt, outputFD, numPvContributors);
829+
valuesToFill.push_back(occ);
830+
}
831+
if (storeProperLifetime) {
832+
valuesToFill.push_back(properLifetime);
791833
}
834+
registry.get<THnSparse>(HIST("hnLcVarsWithBdt"))->Fill(valuesToFill.data());
792835
} else {
836+
std::vector<double> valuesToFill{massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast<double>(numPvContributors)};
793837
if (storeOccupancy && occEstimator != o2::hf_occupancy::OccupancyEstimator::None) {
794-
registry.get<THnSparse>(HIST("hnLcVars"))->Fill(massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors, occ);
795-
} else {
796-
registry.get<THnSparse>(HIST("hnLcVars"))->Fill(massLc, pt, cent, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, numPvContributors);
838+
valuesToFill.push_back(occ);
839+
}
840+
if (storeProperLifetime) {
841+
valuesToFill.push_back(properLifetime);
797842
}
843+
registry.get<THnSparse>(HIST("hnLcVars"))->Fill(valuesToFill.data());
798844
}
799845
}
800846
}

0 commit comments

Comments
 (0)