Skip to content

Commit cbb1830

Browse files
sustripathySushanta Tripathyalibuild
authored
[PWGCF] Fixing minor bugs related to mixed-event histograms (#16321)
Co-authored-by: Sushanta Tripathy <sushantatripathy@ip46-75.eduroam-employee.wireless.lu.se> Co-authored-by: ALICE Action Bot <alibuild@cern.ch>
1 parent f9d02c6 commit cbb1830

1 file changed

Lines changed: 153 additions & 120 deletions

File tree

PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx

Lines changed: 153 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,24 +1739,26 @@ struct Lambdastarproxy {
17391739
// Helpers for invariant-mass kinematics
17401740
static float phiFromPxPy(float px, float py)
17411741
{
1742-
return std::atan2(py, px);
1742+
return RecoDecay::constrainAngle(std::atan2(py, px), -o2::constants::math::PI);
17431743
}
17441744

1745-
static float rapidityFromEPz(double e, double pz)
1745+
static float ptFromPxPy(float px, float py)
17461746
{
1747-
const double num = e + pz;
1748-
const double den = e - pz;
1749-
if (num <= 0.0 || den <= 0.0) {
1750-
return 0.f;
1751-
}
1752-
return static_cast<float>(Half * std::log(num / den));
1747+
return RecoDecay::pt(std::array{px, py});
1748+
}
1749+
1750+
static float rapidityFromMomentumAndMass(float px, float py, float pz, double mass)
1751+
1752+
{
1753+
return RecoDecay::y(std::array{px, py, pz}, mass);
17531754
}
17541755

17551756
// Mixed-event pool entry for pK / proxy background (AO2D only)
17561757
struct LStarMixEventEntry {
17571758
float mult = 0.f;
17581759
float zvtx = 0.f;
17591760
std::vector<KaonCand> kaons;
1761+
std::vector<ProtonCand> protons;
17601762
std::vector<ProxyCand> proxies;
17611763
};
17621764

@@ -1966,56 +1968,44 @@ struct Lambdastarproxy {
19661968
"pK invariant mass (like-sign);M_{pK} (GeV/c^{2});Counts",
19671969
HistType::kTH1F, {massAxis});
19681970

1969-
// Invariant-mass vs pair pT (use p_{T} of pK system)
1970-
histos.add("hInvMassPKUnlikeVsPt",
1971-
"pK invariant mass vs p_{T} (unlike-sign);M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);Counts",
1972-
HistType::kTH2F, {massAxis, ptAxis});
1973-
histos.add("hInvMassPKLikeVsPt",
1974-
"pK invariant mass vs p_{T} (like-sign);M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);Counts",
1975-
HistType::kTH2F, {massAxis, ptAxis});
1976-
1977-
// THnSparse for invariant-mass analysis (mass, pT, y, phi)
1971+
// THnSparse for invariant-mass analysis (mass, pT, multiplicity/centrality)
19781972
if (lstarEnableSparse.value != 0) {
19791973
histos.add("hLambdaStarPKUnlikeSparse",
1980-
"#Lambda^{*}(1520) pK unlike-sign candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);y_{pK};#varphi_{pK}",
1974+
"#Lambda^{*}(1520) pK unlike-sign candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);multiplicity/centrality",
19811975
HistType::kTHnSparseF,
1982-
{AxisSpec{400, 1.3, 1.9, "M_{pK} (GeV/c^{2})"},
1983-
AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"},
1984-
AxisSpec{60, -1.5, 1.5, "y_{pK}"},
1985-
AxisSpec{64, -3.2, 3.2, "#varphi_{pK}"}, centAxis});
1976+
{AxisSpec{400, 1.4, 1.8, "M_{pK} (GeV/c^{2})"},
1977+
AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"}, centAxis});
19861978

19871979
histos.add("hLambdaStarPKLikeSparse",
1988-
"#Lambda^{*}(1520) pK like-sign candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);y_{pK};#varphi_{pK}",
1980+
"#Lambda^{*}(1520) pK like-sign candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);multiplicity/centrality",
19891981
HistType::kTHnSparseF,
1990-
{AxisSpec{400, 1.3, 1.9, "M_{pK} (GeV/c^{2})"},
1991-
AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"},
1992-
AxisSpec{60, -1.5, 1.5, "y_{pK}"},
1993-
AxisSpec{64, -3.2, 3.2, "#varphi_{pK}"}, centAxis});
1982+
{AxisSpec{400, 1.4, 1.8, "M_{pK} (GeV/c^{2})"},
1983+
AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"}, centAxis});
19941984

19951985
histos.add("hLambdaStarPKMixedSparse",
1996-
"#Lambda^{*}(1520) pK mixed-event candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);y_{pK};#varphi_{pK}",
1986+
"#Lambda^{*}(1520) pK mixed-event candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);multiplicity/centrality",
19971987
HistType::kTHnSparseF,
1998-
{AxisSpec{400, 1.3, 1.9, "M_{pK} (GeV/c^{2})"},
1999-
AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"},
2000-
AxisSpec{60, -1.5, 1.5, "y_{pK}"},
2001-
AxisSpec{64, -3.2, 3.2, "#varphi_{pK}"}, centAxis});
1988+
{AxisSpec{400, 1.4, 1.8, "M_{pK} (GeV/c^{2})"},
1989+
AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"}, centAxis});
20021990

2003-
// THnSparse for deuteron-proxy invariant-mass analysis (mass, pT, y, phi)
1991+
// THnSparse for deuteron-proxy invariant-mass analysis (mass, pT, multiplicity/centrality)
20041992
histos.add("hLambdaStarProxySparse",
2005-
"#Lambda^{*}(1520) deuteron-proxy candidates;M_{p_{proxy}K} (GeV/c^{2});p_{T}^{p_{proxy}K} (GeV/c);y_{p_{proxy}K};#varphi_{p_{proxy}K}",
1993+
"#Lambda^{*}(1520) deuteron-proxy candidates;M_{p_{proxy}K} (GeV/c^{2});p_{T}^{p_{proxy}K} (GeV/c);multiplicity/centrality",
1994+
HistType::kTHnSparseF,
1995+
{AxisSpec{400, 1.4, 1.8, "M_{p_{proxy}K} (GeV/c^{2})"},
1996+
AxisSpec{100, 0., 10., "p_{T}^{p_{proxy}K} (GeV/c)"}, centAxis});
1997+
1998+
histos.add("hLambdaStarProxyLikeSparse",
1999+
"#Lambda^{*}(1520) deuteron-proxy like-sign candidates;M_{p_{proxy}K} (GeV/c^{2});p_{T}^{p_{proxy}K} (GeV/c);multiplicity/centrality",
20062000
HistType::kTHnSparseF,
2007-
{AxisSpec{400, 1.3, 1.9, "M_{p_{proxy}K} (GeV/c^{2})"},
2008-
AxisSpec{100, 0., 10., "p_{T}^{p_{proxy}K} (GeV/c)"},
2009-
AxisSpec{60, -1.5, 1.5, "y_{p_{proxy}K}"},
2010-
AxisSpec{64, -3.2, 3.2, "#varphi_{p_{proxy}K}"}, centAxis});
2001+
{AxisSpec{400, 1.4, 1.8, "M_{p_{proxy}K} (GeV/c^{2})"},
2002+
AxisSpec{100, 0., 10., "p_{T}^{p_{proxy}K} (GeV/c)"}, centAxis});
20112003

20122004
histos.add("hLambdaStarProxyMixedSparse",
2013-
"#Lambda^{*}(1520) deuteron-proxy mixed-event candidates;M_{p_{proxy}K} (GeV/c^{2});p_{T}^{p_{proxy}K} (GeV/c);y_{p_{proxy}K};#varphi_{p_{proxy}K}",
2005+
"#Lambda^{*}(1520) deuteron-proxy mixed-event candidates;M_{p_{proxy}K} (GeV/c^{2});p_{T}^{p_{proxy}K} (GeV/c);multiplicity/centrality",
20142006
HistType::kTHnSparseF,
2015-
{AxisSpec{400, 1.3, 1.9, "M_{p_{proxy}K} (GeV/c^{2})"},
2016-
AxisSpec{100, 0., 10., "p_{T}^{p_{proxy}K} (GeV/c)"},
2017-
AxisSpec{60, -1.5, 1.5, "y_{p_{proxy}K}"},
2018-
AxisSpec{64, -3.2, 3.2, "#varphi_{p_{proxy}K}"}, centAxis});
2007+
{AxisSpec{400, 1.4, 1.8, "M_{p_{proxy}K} (GeV/c^{2})"},
2008+
AxisSpec{100, 0., 10., "p_{T}^{p_{proxy}K} (GeV/c)"}, centAxis});
20192009
}
20202010

20212011
// Deuteron-proxy invariant mass (p_{proxy} from d/2 combined with K)
@@ -2317,15 +2307,9 @@ struct Lambdastarproxy {
23172307
static double invariantMass(float px1, float py1, float pz1, double m1,
23182308
float px2, float py2, float pz2, double m2)
23192309
{
2320-
const double e1 = std::sqrt(m1 * m1 + px1 * px1 + py1 * py1 + pz1 * pz1);
2321-
const double e2 = std::sqrt(m2 * m2 + px2 * px2 + py2 * py2 + pz2 * pz2);
2322-
const double ex = px1 + px2;
2323-
const double ey = py1 + py2;
2324-
const double ez = pz1 + pz2;
2325-
const double eTot = e1 + e2;
2326-
const double p2Tot = ex * ex + ey * ey + ez * ez;
2327-
const double m2Tot = eTot * eTot - p2Tot;
2328-
return m2Tot > 0. ? std::sqrt(m2Tot) : 0.;
2310+
return RecoDecay::m(std::array{std::array{px1, py1, pz1},
2311+
std::array{px2, py2, pz2}},
2312+
std::array{m1, m2});
23292313
}
23302314

23312315
void process(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks)
@@ -2635,12 +2619,15 @@ struct Lambdastarproxy {
26352619
kaonCands.push_back(KaonCand{pxK, pyK, pzK, static_cast<int>(trkK.sign()), static_cast<int>(trkK.globalIndex())});
26362620
}
26372621

2638-
if (proxyCands.empty() || kaonCands.empty()) {
2639-
// still update mixing buffer so that later events can mix with this one
2622+
if (kaonCands.empty()) {
2623+
// Still update mixing buffer so that later events can mix with this one.
2624+
// The pK mixed-event background needs stored protons, while the proxy background
2625+
// needs stored proxy candidates. Therefore, do not require proxy candidates here.
26402626
LStarMixEventEntry entry;
26412627
entry.mult = eventMult;
26422628
entry.zvtx = collision.posZ();
26432629
entry.kaons = std::move(kaonCands);
2630+
entry.protons = std::move(protonCands);
26442631
entry.proxies = std::move(proxyCands);
26452632
mLStarMixEvents.push_front(std::move(entry));
26462633
if (mLStarMixEvents.size() > static_cast<size_t>(lstarNoMixedEvents.value)) {
@@ -2649,103 +2636,148 @@ struct Lambdastarproxy {
26492636
return;
26502637
}
26512638

2639+
const bool hasProtonCandidates = !protonCands.empty();
2640+
const bool hasProxyCandidates = !proxyCands.empty();
2641+
26522642
// --- SAME-EVENT: genuine pK #Lambda^{*} candidates ---
2653-
for (auto const& pr : protonCands) {
2654-
for (auto const& k : kaonCands) {
2655-
if (pr.tid == k.tid) {
2656-
continue;
2657-
}
2658-
const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton,
2659-
k.px, k.py, k.pz, MassKaonCharged);
2643+
if (hasProtonCandidates) {
2644+
for (auto const& pr : protonCands) {
2645+
for (auto const& k : kaonCands) {
2646+
if (pr.tid == k.tid) {
2647+
continue;
2648+
}
2649+
const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton,
2650+
k.px, k.py, k.pz, MassKaonCharged);
26602651

2661-
const float pxTot = pr.px + k.px;
2662-
const float pyTot = pr.py + k.py;
2663-
const float pzTot = pr.pz + k.pz;
2664-
const float ptPair = std::sqrt(pxTot * pxTot + pyTot * pyTot);
2665-
const float phiPair = phiFromPxPy(pxTot, pyTot);
2652+
const float pxTot = pr.px + k.px;
2653+
const float pyTot = pr.py + k.py;
2654+
const float pzTot = pr.pz + k.pz;
2655+
const float ptPair = ptFromPxPy(pxTot, pyTot);
26662656

2667-
const double eTot = std::sqrt(mass * mass + static_cast<double>(pxTot) * pxTot +
2668-
static_cast<double>(pyTot) * pyTot + static_cast<double>(pzTot) * pzTot);
2669-
const float yPair = rapidityFromEPz(eTot, pzTot);
2657+
const float yPair = rapidityFromMomentumAndMass(pxTot, pyTot, pzTot, mass);
26702658

2671-
if (std::abs(yPair) > lstarLambdaAbsYMax.value) {
2672-
continue;
2673-
}
2674-
2675-
const bool unlikeSignPK = (pr.charge * k.charge) < 0;
2676-
if (unlikeSignPK) {
2677-
histos.fill(HIST("hInvMassPKUnlike"), mass);
2678-
histos.fill(HIST("hInvMassPKUnlikeVsPt"), mass, ptPair);
2679-
if (lstarEnableSparse.value != 0) {
2680-
histos.fill(HIST("hLambdaStarPKUnlikeSparse"), mass, ptPair, yPair, phiPair, eventMult);
2659+
if (std::abs(yPair) > lstarLambdaAbsYMax.value) {
2660+
continue;
26812661
}
2682-
} else {
2683-
histos.fill(HIST("hInvMassPKLike"), mass);
2684-
histos.fill(HIST("hInvMassPKLikeVsPt"), mass, ptPair);
2685-
if (lstarEnableSparse.value != 0) {
2686-
histos.fill(HIST("hLambdaStarPKLikeSparse"), mass, ptPair, yPair, phiPair, eventMult);
2662+
2663+
const bool unlikeSignPK = (pr.charge * k.charge) < 0;
2664+
if (unlikeSignPK) {
2665+
histos.fill(HIST("hInvMassPKUnlike"), mass);
2666+
if (lstarEnableSparse.value != 0) {
2667+
histos.fill(HIST("hLambdaStarPKUnlikeSparse"), mass, ptPair, eventMult);
2668+
}
2669+
} else {
2670+
histos.fill(HIST("hInvMassPKLike"), mass);
2671+
if (lstarEnableSparse.value != 0) {
2672+
histos.fill(HIST("hLambdaStarPKLikeSparse"), mass, ptPair, eventMult);
2673+
}
26872674
}
26882675
}
26892676
}
26902677
}
26912678

26922679
// --- SAME-EVENT: proxy (d/2) + K ---
2693-
for (auto const& pr : proxyCands) {
2694-
for (auto const& k : kaonCands) {
2695-
if (pr.tid == k.tid)
2696-
continue; // sanity check: should never match, but just in case of bug in candidate-building logic
2697-
const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, k.px, k.py, k.pz, MassKaonCharged);
2698-
2699-
const float pxTot = pr.px + k.px;
2700-
const float pyTot = pr.py + k.py;
2701-
const float pzTot = pr.pz + k.pz;
2702-
const float ptPair = std::sqrt(pxTot * pxTot + pyTot * pyTot);
2703-
const float phiPair = phiFromPxPy(pxTot, pyTot);
2704-
2705-
const double eTot = std::sqrt(mass * mass + static_cast<double>(pxTot) * pxTot + static_cast<double>(pyTot) * pyTot + static_cast<double>(pzTot) * pzTot);
2706-
const float yPair = rapidityFromEPz(eTot, pzTot);
2707-
2708-
// Inclusive invariant-mass spectrum for the #Lambda^{*} proxy (d/2 + K)
2709-
histos.fill(HIST("hDeuteronProxyMass"), mass);
2710-
if (lstarEnableSparse.value != 0) {
2711-
histos.fill(HIST("hLambdaStarProxySparse"), mass, ptPair, yPair, phiPair, eventMult);
2680+
if (hasProxyCandidates) {
2681+
for (auto const& pr : proxyCands) {
2682+
for (auto const& k : kaonCands) {
2683+
if (pr.tid == k.tid)
2684+
continue; // sanity check: should never match, but just in case of bug in candidate-building logic
2685+
const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, k.px, k.py, k.pz, MassKaonCharged);
2686+
2687+
const float pxTot = pr.px + k.px;
2688+
const float pyTot = pr.py + k.py;
2689+
const float ptPair = ptFromPxPy(pxTot, pyTot);
2690+
2691+
// Inclusive invariant-mass spectrum for the #Lambda^{*} proxy (d/2 + K)
2692+
histos.fill(HIST("hDeuteronProxyMass"), mass);
2693+
if (lstarEnableSparse.value != 0) {
2694+
histos.fill(HIST("hLambdaStarProxySparse"), mass, ptPair, eventMult);
2695+
2696+
// Like-sign proxy background: proxy and kaon have the same charge sign.
2697+
// Here the proxy charge follows the original deuteron-candidate charge.
2698+
if ((pr.charge * k.charge) > 0) {
2699+
histos.fill(HIST("hLambdaStarProxyLikeSparse"), mass, ptPair, eventMult);
2700+
}
2701+
}
27122702
}
27132703
}
27142704
}
27152705

2716-
// --- MIXED-EVENT: current proxies + previous-event kaons ---
2706+
// --- MIXED-EVENT: current kaons + previous-event real protons ---
2707+
// This fills the standard pK mixed-event background.
27172708
for (auto const& prev : mLStarMixEvents) {
2718-
if (std::abs(prev.zvtx - collision.posZ()) > lstarMixZvtxMax.value)
2709+
if (std::abs(prev.zvtx - collision.posZ()) > lstarMixZvtxMax.value) {
27192710
continue;
2720-
if (std::abs(prev.mult - eventMult) > lstarMixMultMax.value)
2711+
}
2712+
if (std::abs(prev.mult - eventMult) > lstarMixMultMax.value) {
27212713
continue;
2722-
if (prev.kaons.empty()) {
2714+
}
2715+
if (prev.protons.empty()) {
27232716
continue;
27242717
}
27252718

2726-
for (auto const& pr : proxyCands) {
2727-
for (auto const& k : prev.kaons) {
2728-
// convention: mix for unlike-sign only (resonance background)
2719+
for (auto const& pr : prev.protons) {
2720+
for (auto const& k : kaonCands) {
2721+
// Unlike-sign pK mixed-event background.
27292722
if ((pr.charge * k.charge) >= 0) {
27302723
continue;
27312724
}
2732-
if (pr.tid == k.tid)
2733-
continue; // sanity check: should never match, but just in case of bug in candidate-building logic
2734-
2735-
const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, k.px, k.py, k.pz, MassKaonCharged);
27362725

2726+
const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton,
2727+
k.px, k.py, k.pz, MassKaonCharged);
27372728
const float pxTot = pr.px + k.px;
27382729
const float pyTot = pr.py + k.py;
27392730
const float pzTot = pr.pz + k.pz;
2740-
const float ptPair = std::sqrt(pxTot * pxTot + pyTot * pyTot);
2741-
const float phiPair = phiFromPxPy(pxTot, pyTot);
2731+
const float ptPair = ptFromPxPy(pxTot, pyTot);
27422732

2743-
const double eTot = std::sqrt(mass * mass + static_cast<double>(pxTot) * pxTot + static_cast<double>(pyTot) * pyTot + static_cast<double>(pzTot) * pzTot);
2744-
const float yPair = rapidityFromEPz(eTot, pzTot);
2733+
const float yPair = rapidityFromMomentumAndMass(pxTot, pyTot, pzTot, mass);
2734+
if (std::abs(yPair) > lstarLambdaAbsYMax.value) {
2735+
continue;
2736+
}
27452737

2746-
// Fill mixed-event THnSparse (proxy only)
27472738
if (lstarEnableSparse.value != 0) {
2748-
histos.fill(HIST("hLambdaStarProxyMixedSparse"), mass, ptPair, yPair, phiPair, eventMult);
2739+
histos.fill(HIST("hLambdaStarPKMixedSparse"), mass, ptPair, eventMult);
2740+
}
2741+
}
2742+
}
2743+
}
2744+
2745+
// --- MIXED-EVENT: current proxies + previous-event kaons ---
2746+
// This fills the deuteron-proxy mixed-event background.
2747+
if (hasProxyCandidates) {
2748+
for (auto const& prev : mLStarMixEvents) {
2749+
if (std::abs(prev.zvtx - collision.posZ()) > lstarMixZvtxMax.value) {
2750+
continue;
2751+
}
2752+
if (std::abs(prev.mult - eventMult) > lstarMixMultMax.value) {
2753+
continue;
2754+
}
2755+
if (prev.kaons.empty()) {
2756+
continue;
2757+
}
2758+
2759+
for (auto const& pr : proxyCands) {
2760+
for (auto const& k : prev.kaons) {
2761+
// Unlike-sign proxy-K mixed-event background.
2762+
if ((pr.charge * k.charge) >= 0) {
2763+
continue;
2764+
}
2765+
2766+
const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton,
2767+
k.px, k.py, k.pz, MassKaonCharged);
2768+
const float pxTot = pr.px + k.px;
2769+
const float pyTot = pr.py + k.py;
2770+
const float pzTot = pr.pz + k.pz;
2771+
const float ptPair = ptFromPxPy(pxTot, pyTot);
2772+
2773+
const float yPair = rapidityFromMomentumAndMass(pxTot, pyTot, pzTot, mass);
2774+
if (std::abs(yPair) > lstarLambdaAbsYMax.value) {
2775+
continue;
2776+
}
2777+
2778+
if (lstarEnableSparse.value != 0) {
2779+
histos.fill(HIST("hLambdaStarProxyMixedSparse"), mass, ptPair, eventMult);
2780+
}
27492781
}
27502782
}
27512783
}
@@ -2756,6 +2788,7 @@ struct Lambdastarproxy {
27562788
entry.mult = eventMult;
27572789
entry.zvtx = collision.posZ();
27582790
entry.kaons = std::move(kaonCands);
2791+
entry.protons = std::move(protonCands);
27592792
entry.proxies = std::move(proxyCands);
27602793

27612794
mLStarMixEvents.push_front(std::move(entry));

0 commit comments

Comments
 (0)