Skip to content

Commit cbd2638

Browse files
sustripathySushanta Tripathy
andauthored
[PWGCF] Update in PID strategy and QA (#16834)
Co-authored-by: Sushanta Tripathy <sushantatripathy@Sushantas-MacBook-Pro-M4-Max.local>
1 parent 17fe1e4 commit cbd2638

1 file changed

Lines changed: 43 additions & 96 deletions

File tree

PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx

Lines changed: 43 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1711,6 +1711,7 @@ struct Lambdastarproxy {
17111711
Configurable<float> lstarCutNsigmaTPCDe{"lstarCutNsigmaTPCDe", float{NsigmaTPCDefault}, "|nSigma^{TPC}_{d}| cut"};
17121712
Configurable<float> lstarCutNsigmaTOFDe{"lstarCutNsigmaTOFDe", float{NsigmaTOFDefault}, "|nSigma^{TOF}_{d}| cut"};
17131713
Configurable<int> lstarEnableTOFNsigmaCutDe{"lstarEnableTOFNsigmaCutDe", 0, "Enable deuteron-only TOF nSigma cut in PID strategy 2"};
1714+
Configurable<int> lstarProxyUseProtonPIDAsDeuteron{"lstarProxyUseProtonPIDAsDeuteron", 0, "Closure/control test: keep proxy candidates that pass the normal deuteron selection and are also proton-like, then build p_proxy = p_track/2"};
17141715
// Optional deuteron-only TOF auxiliary selections.
17151716
// Defaults are OFF, so strategy 2 remains TPC nSigma only for deuterons.
17161717
Configurable<int> lstarEnableBetaCutDe{"lstarEnableBetaCutDe", 0, "Enable deuteron-only TOF beta cut using beta() > lstarBetaCutDe"};
@@ -1763,6 +1764,9 @@ struct Lambdastarproxy {
17631764
Configurable<int> lstarNoMixedEvents{"lstarNoMixedEvents", int{NoMixedEventsDefault}, "Number of previous events kept for mixed-event background"};
17641765
Configurable<float> lstarMixZvtxMax{"lstarMixZvtxMax", float{MixZvtxMaxDefault}, "Max |Δzvtx| (cm) for event mixing"};
17651766
Configurable<float> lstarMixMultMax{"lstarMixMultMax", float{MixMultMaxDefault}, "Max |Δmult| for event mixing"};
1767+
// Master switch for PID QA histogram filling.
1768+
// Inclusive PID-QA histograms are filled before final PID cuts, after event/track-quality cuts.
1769+
// Candidate-level nSigma/TOF/DCA histograms are filled after final PID cuts.
17661770
Configurable<int> lstarEnablePidQA{"lstarEnablePidQA", 0, "Enable PID QA histograms (dE/dx, TOF #beta, proxy invariant-mass QA, etc.): 1 = ON, 0 = OFF"};
17671771
Configurable<int> lstarEnableSparse{"lstarEnableSparse", 1, "Enable THnSparse invariant-mass histograms (#Lambda^{*} pK and proxy); 1 = ON, 0 = OFF"};
17681772
Configurable<float> lstarLambdaAbsYMax{"lstarLambdaAbsYMax", 0.5f, "Max |y_{pK}| (or y_{proxy K}) for #Lambda^{*} candidates"};
@@ -2104,6 +2108,7 @@ struct Lambdastarproxy {
21042108
"#Lambda^{*} proxy invariant mass from (d/2 + K);M_{p_{proxy}K} (GeV/c^{2});Counts",
21052109
HistType::kTH1F, {massAxis});
21062110

2111+
// Inclusive PID QA before final candidate PID cuts: after track-quality cuts only
21072112
// TPC dE/dx vs total momentum
21082113
histos.add("hTPCdEdxVsP",
21092114
"TPC dE/dx vs p;p (GeV/c);dE/dx (arb. units);Counts",
@@ -2114,7 +2119,8 @@ struct Lambdastarproxy {
21142119
"TOF #beta vs p;p (GeV/c);#beta_{TOF};Counts",
21152120
HistType::kTH2F, {pAxis, betaAxis});
21162121

2117-
// --- Per-species PID QA (tagged) ---
2122+
// --- Per-species inclusive PID QA before final candidate PID cuts ---
2123+
// Species tagging here uses classifyPidSpecies() and is meant only for QA.
21182124
histos.add("hTPCdEdxVsP_Pi",
21192125
"TPC dE/dx vs p (tagged #pi);p (GeV/c);dE/dx (arb. units);Counts",
21202126
HistType::kTH2F, {pAxis, dEdxAxis});
@@ -2204,7 +2210,7 @@ struct Lambdastarproxy {
22042210
"TOF n#sigma_{K} vs p; p (GeV/c); n#sigma^{TOF}_{K};Counts",
22052211
HistType::kTH2F, {pAxis, nsAxis});
22062212

2207-
// --- Additional pT-based PID QA for the final selected K/p/d candidates ---
2213+
// --- Candidate PID QA after final selected K/p/d PID cuts ---
22082214
// These histograms are needed for PID studies in the same pT intervals used by the analysis.
22092215
histos.add("hTOFBetaVsPt_K",
22102216
"TOF #beta vs p_{T} for selected K;p_{T} (GeV/c);#beta_{TOF};Counts",
@@ -2451,16 +2457,15 @@ struct Lambdastarproxy {
24512457
}
24522458

24532459
if (lstarPidStrategy.value == PidStrategyNucleiDeuteronTPC) {
2454-
// For deuterons, follow the default idea of the official nuclei task:
2455-
// use TPC nσ as the main hard PID selection.
2460+
// For deuterons, use TPC nσ as the main hard PID selection.
2461+
// If the optional deuteron TOF nσ cut is enabled, apply it only when
2462+
// the track has a valid TOF match. Tracks without TOF are kept with
2463+
// the TPC-only decision, avoiding an additional TOF-matching efficiency loss.
24562464
if (isDeuteron) {
24572465
if (std::abs(nsTPC) >= tpcCut) {
24582466
return false;
24592467
}
2460-
if (lstarEnableTOFNsigmaCutDe.value != 0) {
2461-
if (!hasTof) {
2462-
return false;
2463-
}
2468+
if (lstarEnableTOFNsigmaCutDe.value != 0 && hasTof) {
24642469
return std::abs(nsTOF) < tofCut;
24652470
}
24662471
return true;
@@ -2580,87 +2585,6 @@ struct Lambdastarproxy {
25802585
constexpr double MassProton = o2::constants::physics::MassProton;
25812586
constexpr double MassKaonCharged = o2::constants::physics::MassKaonCharged;
25822587

2583-
// --- Inclusive PID QA: keep #pi/K/p/d bands in TPC dE/dx and TOF beta plots ---
2584-
if (lstarEnablePidQA.value != 0) {
2585-
for (auto const& trk : tracks) {
2586-
if (trk.pt() < lstarCutPtMin.value || std::abs(trk.eta()) > lstarCutEtaMax.value) {
2587-
continue;
2588-
}
2589-
if (!passTrackQuality(trk)) {
2590-
continue;
2591-
}
2592-
if (trk.sign() == 0) {
2593-
continue;
2594-
}
2595-
// Inclusive PID QA
2596-
fillTPCdEdxVsPIfAvailable(trk);
2597-
fillTOFBetaVsPIfAvailable(trk);
2598-
2599-
// Per-species PID-QA (tagged) histograms
2600-
const int sp = classifyPidSpecies(trk);
2601-
switch (sp) {
2602-
case 0: { // pion
2603-
if constexpr (requires { trk.tpcSignal(); }) {
2604-
histos.fill(HIST("hTPCdEdxVsP_Pi"), trk.p(), trk.tpcSignal());
2605-
}
2606-
if constexpr (requires { trk.beta(); }) {
2607-
const bool hasTof = hasTOFMatch(trk);
2608-
const float beta = trk.beta();
2609-
if (hasTof && beta > TofBetaMin && beta < TofBetaMax) {
2610-
histos.fill(HIST("hTOFBetaVsP_Pi"), trk.p(), beta);
2611-
}
2612-
}
2613-
break;
2614-
}
2615-
2616-
case 1: { // kaon
2617-
if constexpr (requires { trk.tpcSignal(); }) {
2618-
histos.fill(HIST("hTPCdEdxVsP_K"), trk.p(), trk.tpcSignal());
2619-
}
2620-
if constexpr (requires { trk.beta(); }) {
2621-
const bool hasTof = hasTOFMatch(trk);
2622-
const float beta = trk.beta();
2623-
if (hasTof && beta > TofBetaMin && beta < TofBetaMax) {
2624-
histos.fill(HIST("hTOFBetaVsP_K"), trk.p(), beta);
2625-
}
2626-
}
2627-
break;
2628-
}
2629-
2630-
case 2: { // proton
2631-
if constexpr (requires { trk.tpcSignal(); }) {
2632-
histos.fill(HIST("hTPCdEdxVsP_P"), trk.p(), trk.tpcSignal());
2633-
}
2634-
if constexpr (requires { trk.beta(); }) {
2635-
const bool hasTof = hasTOFMatch(trk);
2636-
const float beta = trk.beta();
2637-
if (hasTof && beta > TofBetaMin && beta < TofBetaMax) {
2638-
histos.fill(HIST("hTOFBetaVsP_P"), trk.p(), beta);
2639-
}
2640-
}
2641-
break;
2642-
}
2643-
2644-
case 3: { // deuteron
2645-
if constexpr (requires { trk.tpcSignal(); }) {
2646-
histos.fill(HIST("hTPCdEdxVsP_D"), trk.p(), trk.tpcSignal());
2647-
}
2648-
if constexpr (requires { trk.beta(); }) {
2649-
const bool hasTof = hasTOFMatch(trk);
2650-
const float beta = trk.beta();
2651-
if (hasTof && beta > TofBetaMin && beta < TofBetaMax) {
2652-
histos.fill(HIST("hTOFBetaVsP_D"), trk.p(), beta);
2653-
}
2654-
}
2655-
break;
2656-
}
2657-
2658-
default:
2659-
break;
2660-
}
2661-
}
2662-
}
2663-
26642588
std::vector<KaonCand> kaonCands;
26652589
std::vector<ProxyCand> proxyCands;
26662590
std::vector<ProtonCand> protonCands;
@@ -2670,7 +2594,9 @@ struct Lambdastarproxy {
26702594

26712595
float eventMultFallback = 0.f; // fallback mixing variable: number of selected charged tracks (after quality cuts)
26722596

2673-
// Inclusive PID QA loop: count all selected charged tracks for fallback multiplicity
2597+
// Inclusive track loop before final candidate PID cuts.
2598+
// It counts selected charged tracks for fallback multiplicity and when enabled,
2599+
// fills inclusive PID QA after track-quality cuts but before final K/p/d PID cuts.
26742600
for (auto const& trk : tracks) {
26752601
if (trk.pt() < lstarCutPtMin.value || std::abs(trk.eta()) > lstarCutEtaMax.value) {
26762602
continue;
@@ -2769,23 +2695,44 @@ struct Lambdastarproxy {
27692695
const float etaD = trkD.eta();
27702696
const float phiD = trkD.phi();
27712697

2772-
// PID for deuteron candidates
2698+
// PID for proxy candidates.
2699+
// Normal mode: use the standard deuteron PID and build p_proxy = p_d / 2.
2700+
// Closure/control mode: select the subset of standard deuteron-proxy candidates
2701+
// that are also proton-like. This tests proton contamination inside the deuteron
2702+
// selection, not all proton candidates.
2703+
const bool useProtonAsProxy = (lstarProxyUseProtonPIDAsDeuteron.value != 0);
2704+
27732705
const float nsTPCDe = trkD.tpcNSigmaDe();
27742706
const float nsTOFDe = trkD.tofNSigmaDe();
27752707
const bool hasTofDe = hasTOFMatch(trkD);
2708+
27762709
if (!passOptionalDeuteronTOFExtras(trkD)) {
27772710
continue;
27782711
}
2779-
const bool isDeuteron = passFinalCandidatePID(trkD.pt(), trkD.tpcNSigmaDe(), nsTOFDe, hasTofDe,
2780-
lstarCutNsigmaTPCDe.value, lstarCutNsigmaTOFDe.value,
2781-
lstarPidCircularCutDe.value, lstarPidPtRefDe.value, true);
2782-
if (!isDeuteron) {
2712+
2713+
const bool passesDeuteronSelection = passFinalCandidatePID(ptD, nsTPCDe, nsTOFDe, hasTofDe,
2714+
lstarCutNsigmaTPCDe.value, lstarCutNsigmaTOFDe.value,
2715+
lstarPidCircularCutDe.value, lstarPidPtRefDe.value,
2716+
true);
2717+
if (!passesDeuteronSelection) {
27832718
continue;
27842719
}
27852720

2721+
if (useProtonAsProxy) {
2722+
const float nsTPCPrAsProxy = trkD.tpcNSigmaPr();
2723+
const float nsTOFPrAsProxy = trkD.tofNSigmaPr();
2724+
const bool passesProtonSelection = passFinalCandidatePID(ptD, nsTPCPrAsProxy, nsTOFPrAsProxy, hasTofDe,
2725+
lstarCutNsigmaTPCPr.value, lstarCutNsigmaTOFPr.value,
2726+
lstarPidCircularCutPr.value, lstarPidPtRefPr.value,
2727+
false);
2728+
if (!passesProtonSelection) {
2729+
continue;
2730+
}
2731+
}
2732+
27862733
const double pD = static_cast<double>(ptD) * std::cosh(static_cast<double>(etaD));
27872734

2788-
// QA histos for deuteron PID and kinematics
2735+
// Candidate QA after final deuteron PID cut
27892736
if (lstarEnablePidQA.value != 0) {
27902737
histos.fill(HIST("hDeuteronProxyPt"), ptD);
27912738
histos.fill(HIST("hDeuteronProxyEta"), etaD);

0 commit comments

Comments
 (0)