Skip to content

Commit 89253ce

Browse files
authored
[PWGLF] Fix event mixing bug for two daughter mixing (#13809)
1 parent ed009f1 commit 89253ce

File tree

1 file changed

+94
-87
lines changed

1 file changed

+94
-87
lines changed

PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx

Lines changed: 94 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,6 @@ struct lambdaspincorrderived {
531531
const ROOT::Math::PtEtaPhiMVector& daughpart1, const ROOT::Math::PtEtaPhiMVector& daughpart2,
532532
int datatype, float mixpairweight, int mixedLeg)
533533
{
534-
535534
auto lambda1Mass = 0.0;
536535
auto lambda2Mass = 0.0;
537536
if (!usePDGM) {
@@ -622,35 +621,29 @@ struct lambdaspincorrderived {
622621
double epsWeightMixedLeg = 1.0;
623622
if (useweight && datatype == 1) { // only for ME
624623
if (mixedLeg == 1) {
625-
// Only leg 1 is from the mixing pool
626624
double w1 = 1.0;
627-
if (tag1 == 0) { // Λ
628-
if (hweight1) {
629-
w1 = hweight1->GetBinContent(hweight1->FindBin(dphi1, deta1, pt1));
630-
}
631-
} else { // Λbar
632-
if (hweight4) {
633-
w1 = hweight4->GetBinContent(hweight4->FindBin(dphi1, deta1, pt1));
634-
}
635-
}
636-
if (w1 > 0.0 && std::isfinite(w1)) {
637-
epsWeightMixedLeg = w1;
625+
if (tag1 == 0 && tag2 == 0) {
626+
w1 = hweight1->GetBinContent(hweight1->FindBin(dphi1, deta1, pt1));
627+
} else if (tag1 == 0 && tag2 == 1) {
628+
w1 = hweight2->GetBinContent(hweight2->FindBin(dphi1, deta1, pt1));
629+
} else if (tag1 == 1 && tag2 == 0) {
630+
w1 = hweight3->GetBinContent(hweight3->FindBin(dphi1, deta1, pt1));
631+
} else if (tag1 == 1 && tag2 == 1) {
632+
w1 = hweight4->GetBinContent(hweight4->FindBin(dphi1, deta1, pt1));
638633
}
634+
epsWeightMixedLeg = w1;
639635
} else if (mixedLeg == 2) {
640-
// Only leg 2 is from the mixing pool
641636
double w2 = 1.0;
642-
if (tag2 == 0) { // Λ
643-
if (hweight12) {
644-
w2 = hweight12->GetBinContent(hweight12->FindBin(dphi2, deta2, pt2));
645-
}
646-
} else { // Λbar
647-
if (hweight42) {
648-
w2 = hweight42->GetBinContent(hweight42->FindBin(dphi2, deta2, pt2));
649-
}
650-
}
651-
if (w2 > 0.0 && std::isfinite(w2)) {
652-
epsWeightMixedLeg = w2;
637+
if (tag1 == 0 && tag2 == 0) {
638+
w2 = hweight12->GetBinContent(hweight12->FindBin(dphi2, deta1, pt2));
639+
} else if (tag1 == 0 && tag2 == 1) {
640+
w2 = hweight22->GetBinContent(hweight22->FindBin(dphi2, deta1, pt2));
641+
} else if (tag1 == 1 && tag2 == 0) {
642+
w2 = hweight32->GetBinContent(hweight32->FindBin(dphi2, deta1, pt2));
643+
} else if (tag1 == 1 && tag2 == 1) {
644+
w2 = hweight42->GetBinContent(hweight42->FindBin(dphi2, deta2, pt2));
653645
}
646+
epsWeightMixedLeg = w2;
654647
}
655648
}
656649

@@ -697,46 +690,55 @@ struct lambdaspincorrderived {
697690
} else if (datatype == 1) {
698691
double weight = mixpairweight;
699692
if (useweight) {
700-
if (usebothweight) {
701-
weight = mixpairweight / (epsWeightMixedLeg);
702-
} else {
703-
weight = mixpairweight / (epsWeightMixedLeg);
704-
}
693+
weight = mixpairweight / (epsWeightMixedLeg);
705694
}
706695
if (weight <= 0.0) {
707696
weight = 1.0;
708697
}
698+
// LOGF(info, Form("Getting alignment offsets from the CCDB...%2.2f",epsWeightMixedLeg));
709699
histos.fill(HIST("hPtYMix"), particle1.Pt(), particle1.Rapidity(), weight);
710700
if (tag1 == 0 && tag2 == 0) {
711-
histos.fill(HIST("ME_LL"), dphi1, deta1, pt1, mixpairweight);
712-
histos.fill(HIST("ME_LL2"), dphi2, deta2, pt2, mixpairweight);
701+
if (mixedLeg == 1) {
702+
histos.fill(HIST("ME_LL"), dphi1, deta1, pt1, weight);
703+
} else if (mixedLeg == 2) {
704+
histos.fill(HIST("ME_LL2"), dphi2, deta2, pt2, weight);
705+
}
713706
histos.fill(HIST("hSparseLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight);
714707
if (useAdditionalHisto) {
715708
histos.fill(HIST("hSparseRapLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight);
716709
histos.fill(HIST("hSparsePhiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight);
717710
histos.fill(HIST("hSparsePairMassLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight);
718711
}
719712
} else if (tag1 == 0 && tag2 == 1) {
720-
histos.fill(HIST("ME_LAL"), dphi1, deta1, pt1, mixpairweight);
721-
histos.fill(HIST("ME_LAL2"), dphi2, deta2, pt2, mixpairweight);
713+
if (mixedLeg == 1) {
714+
histos.fill(HIST("ME_LAL"), dphi1, deta1, pt1, weight);
715+
} else if (mixedLeg == 2) {
716+
histos.fill(HIST("ME_LAL2"), dphi2, deta2, pt2, weight);
717+
}
722718
histos.fill(HIST("hSparseLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight);
723719
if (useAdditionalHisto) {
724720
histos.fill(HIST("hSparseRapLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight);
725721
histos.fill(HIST("hSparsePhiLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight);
726722
histos.fill(HIST("hSparsePairMassLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight);
727723
}
728724
} else if (tag1 == 1 && tag2 == 0) {
729-
histos.fill(HIST("ME_ALL"), dphi1, deta1, pt1, mixpairweight);
730-
histos.fill(HIST("ME_ALL2"), dphi2, deta2, pt2, mixpairweight);
725+
if (mixedLeg == 1) {
726+
histos.fill(HIST("ME_ALL"), dphi1, deta1, pt1, weight);
727+
} else if (mixedLeg == 2) {
728+
histos.fill(HIST("ME_ALL2"), dphi2, deta2, pt2, weight);
729+
}
731730
histos.fill(HIST("hSparseAntiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight);
732731
if (useAdditionalHisto) {
733732
histos.fill(HIST("hSparseRapAntiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight);
734733
histos.fill(HIST("hSparsePhiAntiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight);
735734
histos.fill(HIST("hSparsePairMassAntiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight);
736735
}
737736
} else if (tag1 == 1 && tag2 == 1) {
738-
histos.fill(HIST("ME_ALAL"), dphi1, deta1, pt1, mixpairweight);
739-
histos.fill(HIST("ME_ALAL2"), dphi2, deta2, pt2, mixpairweight);
737+
if (mixedLeg == 1) {
738+
histos.fill(HIST("ME_ALAL"), dphi1, deta1, pt1, weight);
739+
} else if (mixedLeg == 2) {
740+
histos.fill(HIST("ME_ALAL2"), dphi2, deta2, pt2, weight);
741+
}
740742
histos.fill(HIST("hSparseAntiLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight);
741743
if (useAdditionalHisto) {
742744
histos.fill(HIST("hSparseRapAntiLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight);
@@ -1064,17 +1066,17 @@ struct lambdaspincorrderived {
10641066
}
10651067
PROCESS_SWITCH(lambdaspincorrderived, processMEV3, "Process data ME (first-leg, pair-3D maps)", false);
10661068

1069+
// ---------------------- minimal helpers you already use ----------------------
10671070
static constexpr int N_STATUS = 2; // v0Status ∈ {0,1}
10681071

10691072
struct MixBinner {
1070-
// constructed from the task's configurables; φ is assumed already constrained into [0, 2π)
10711073
float ptMin, ptMax, ptStep;
10721074
float etaMin, etaMax, etaStep;
10731075
float phiMin, phiMax, phiStep;
10741076

1075-
// Mass binning: [1.09, 1.14) with 50 bins (1e-3 GeV/c^2)
1077+
// if you want 1 mass bin (effectively “on/off”), keep nM_=1
10761078
static constexpr float mMin = 1.09f;
1077-
static constexpr float mMax = 1.14f; // exclusive
1079+
static constexpr float mMax = 1.14f;
10781080
static constexpr int nM_ = 1;
10791081
static constexpr float mStep = (mMax - mMin) / nM_;
10801082

@@ -1088,7 +1090,6 @@ struct lambdaspincorrderived {
10881090
ptStep = (ptStep > 0.f ? ptStep : 0.1f);
10891091
etaStep = (etaStep > 0.f ? etaStep : 0.1f);
10901092
phiStep = (phiStep > 0.f ? phiStep : 0.1f);
1091-
10921093
nPt_ = std::max(1, static_cast<int>(std::floor((ptMax - ptMin) / ptStep + 0.5f)));
10931094
nEta_ = std::max(1, static_cast<int>(std::floor((etaMax - etaMin) / etaStep + 0.5f)));
10941095
nPhi_ = std::max(1, static_cast<int>(std::ceil((phiMax - phiMin) / phiStep)));
@@ -1108,19 +1109,18 @@ struct lambdaspincorrderived {
11081109
if (b < 0)
11091110
return -1;
11101111
if (b >= nBins)
1111-
b = nBins - 1; // clamp exact-top edge
1112+
b = nBins - 1;
11121113
return b;
11131114
}
1114-
11151115
inline int ptBin(float pt) const { return binFromValue(pt, ptMin, ptStep, nPt_); }
1116-
inline int etaBin(float eta) const { return binFromValue(eta, etaMin, etaStep, nEta_); }
1117-
inline int phiBin(float phi) const { return binFromValue(phi, phiMin, phiStep, nPhi_); } // φ already constrained upstream
1116+
inline int etaBin(float e) const { return binFromValue(e, etaMin, etaStep, nEta_); }
1117+
inline int phiBin(float ph) const { return binFromValue(ph, phiMin, phiStep, nPhi_); }
11181118
inline int massBin(float m) const { return binFromValue(m, mMin, mStep, nM_); }
11191119
};
11201120

11211121
struct BufferCand {
1122-
int64_t collisionIdx; // from col.index()
1123-
int64_t rowIndex; // global row id in V0s
1122+
int64_t collisionIdx;
1123+
int64_t rowIndex;
11241124
uint8_t v0Status;
11251125
uint16_t ptBin, etaBin, phiBin, mBin;
11261126
};
@@ -1130,16 +1130,16 @@ struct lambdaspincorrderived {
11301130
int64_t rowIndex;
11311131
};
11321132

1133-
// 6D key: (colBin, status, pt, eta, phi, mass)
11341133
static inline size_t linearKey(int colBin, int statBin,
11351134
int ptBin, int etaBin, int phiBin, int mBin,
11361135
int nStatus, int nPt, int nEta, int nPhi, int nM)
11371136
{
11381137
return ((((((static_cast<size_t>(colBin) * nStatus + statBin) * nPt + ptBin) * nEta + etaBin) * nPhi + phiBin) * nM + mBin));
11391138
}
1139+
1140+
// ================================ processMEV4 ================================
11401141
void processMEV4(EventCandidates const& collisions, AllTrackCandidates const& V0s)
11411142
{
1142-
// Build binner from your existing configurables
11431143
MixBinner mb{
11441144
ptMin.value, ptMax.value, ptMix.value, // pT range & step
11451145
v0eta.value, etaMix.value, // |eta| max & step
@@ -1156,9 +1156,7 @@ struct lambdaspincorrderived {
11561156
const size_t nKeys = static_cast<size_t>(nCol) * nStat * nPt * nEta * nPhi * nM;
11571157
std::vector<std::vector<BufferCand>> buffer(nKeys);
11581158

1159-
// =========================
1160-
// PASS 1: fill 6D buffer
1161-
// =========================
1159+
// ---------------- PASS 1: fill the 6D buffer ----------------
11621160
for (auto const& col : collisions) {
11631161
const int colBin = colBinning.getBin(std::make_tuple(col.posz(), col.cent()));
11641162
auto slice = V0s.sliceBy(tracksPerCollisionV0, col.index());
@@ -1178,9 +1176,7 @@ struct lambdaspincorrderived {
11781176
if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0)
11791177
continue;
11801178

1181-
const size_t key = linearKey(colBin, status, ptB, etaB, phiB, mB,
1182-
nStat, nPt, nEta, nPhi, nM);
1183-
1179+
const size_t key = linearKey(colBin, status, ptB, etaB, phiB, mB, nStat, nPt, nEta, nPhi, nM);
11841180
buffer[key].push_back(BufferCand{
11851181
.collisionIdx = static_cast<int64_t>(col.index()),
11861182
.rowIndex = static_cast<int64_t>(t.globalIndex()),
@@ -1192,7 +1188,7 @@ struct lambdaspincorrderived {
11921188
}
11931189
}
11941190

1195-
// Helper: get matches for a given candidate (for mixing one leg)
1191+
// small helper (kept local) to fetch matches for a given candidate from the same 6D bin
11961192
auto makeMatchesFor = [&](auto const& cand,
11971193
int colBinLocal,
11981194
int64_t curColIdx) -> std::vector<MatchRef> {
@@ -1209,33 +1205,21 @@ struct lambdaspincorrderived {
12091205
if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0)
12101206
return matches;
12111207

1212-
const size_t key = linearKey(colBinLocal, status, ptB, etaB, phiB, mB,
1213-
nStat, nPt, nEta, nPhi, nM);
1208+
const size_t key = linearKey(colBinLocal, status, ptB, etaB, phiB, mB, nStat, nPt, nEta, nPhi, nM);
12141209
auto const& binVec = buffer[key];
12151210
if (binVec.empty())
12161211
return matches;
12171212

12181213
matches.reserve(binVec.size());
12191214
for (const auto& bc : binVec) {
12201215
if (bc.collisionIdx == curColIdx)
1221-
continue; // ensure different event
1216+
continue; // different event
12221217
matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex});
12231218
}
1224-
1225-
// Optionally cap number of matches by nEvtMixing
1226-
const int cap = nEvtMixing.value;
1227-
const int n = static_cast<int>(matches.size());
1228-
if (cap > 0 && n > cap) {
1229-
std::shuffle(matches.begin(), matches.end(), rng);
1230-
matches.resize(cap);
1231-
}
1232-
12331219
return matches;
12341220
};
12351221

1236-
// =========================
1237-
// PASS 2: mixing over SE pairs (mix both legs)
1238-
// =========================
1222+
// ---------------- PASS 2: loop over SE pairs and mix both legs ----------------
12391223
for (auto const& collision1 : collisions) {
12401224
const int colBin = colBinning.getBin(std::make_tuple(collision1.posz(), collision1.cent()));
12411225
auto poolA = V0s.sliceBy(tracksPerCollisionV0, collision1.index());
@@ -1259,20 +1243,38 @@ struct lambdaspincorrderived {
12591243
if (t1.pionIndex() == t2.protonIndex())
12601244
continue;
12611245

1262-
// matches for replacing leg 1 and leg 2
1263-
auto matches1 = makeMatchesFor(t1, colBin, curColId); // t1 -> tX
1264-
auto matches2 = makeMatchesFor(t2, colBin, curColId); // t2 -> tY
1246+
// gather matches for both legs from the same 6D bin
1247+
auto matches1 = makeMatchesFor(t1, colBin, curColId); // candidates to replace leg-1
1248+
auto matches2 = makeMatchesFor(t2, colBin, curColId); // candidates to replace leg-2
12651249

1266-
const int n1 = static_cast<int>(matches1.size());
1267-
const int n2 = static_cast<int>(matches2.size());
1268-
if (n1 == 0 && n2 == 0)
1250+
const int n1Eff = static_cast<int>(matches1.size());
1251+
const int n2Eff = static_cast<int>(matches2.size());
1252+
if (n1Eff == 0 && n2Eff == 0)
12691253
continue;
12701254

1271-
// Split "unit" weight between the two modes
1272-
const float w1 = (n1 > 0 ? 0.5f / static_cast<float>(n1) : 0.f);
1273-
const float w2 = (n2 > 0 ? 0.5f / static_cast<float>(n2) : 0.f);
1255+
// per-leg depth (configurable)
1256+
int depth = nEvtMixing.value;
1257+
if (depth <= 0)
1258+
depth = 1;
1259+
1260+
const int n1Take = std::min(depth, n1Eff);
1261+
const int n2Take = std::min(depth, n2Eff);
12741262

1275-
// --- Type A: replace leg 1 → (tX, t2) ---
1263+
// split unit weight between legs if both have mixes; else single leg gets full
1264+
const float w1 = (n1Take > 0 ? ((n2Take > 0 ? 0.5f : 1.0f) / static_cast<float>(n1Take)) : 0.0f);
1265+
const float w2 = (n2Take > 0 ? ((n1Take > 0 ? 0.5f : 1.0f) / static_cast<float>(n2Take)) : 0.0f);
1266+
1267+
// randomize & truncate per-leg matches to requested depth
1268+
if (n1Take > 0) {
1269+
std::shuffle(matches1.begin(), matches1.end(), rng);
1270+
matches1.resize(n1Take);
1271+
}
1272+
if (n2Take > 0) {
1273+
std::shuffle(matches2.begin(), matches2.end(), rng);
1274+
matches2.resize(n2Take);
1275+
}
1276+
1277+
// --- Type A: replace leg 1 (t1 -> tX), keep t2
12761278
for (const auto& m : matches1) {
12771279
auto tX = V0s.iteratorAt(m.rowIndex);
12781280
if (!selectionV0(tX))
@@ -1289,10 +1291,13 @@ struct lambdaspincorrderived {
12891291
const float dPhi = std::fabs(RecoDecay::constrainAngle(lambda1.Phi() - lambda2.Phi(), 0.0F, harmonicDphi));
12901292
histos.fill(HIST("deltaPhiMix"), dPhi, w1);
12911293

1292-
fillHistograms2(tX.v0Status(), t2.v0Status(), lambda1, lambda2, proton1, proton2, 1, w1, 1);
1294+
// datatype=1 (ME), mixedLeg=1
1295+
fillHistograms2(tX.v0Status(), t2.v0Status(),
1296+
lambda1, lambda2, proton1, proton2,
1297+
/*datatype=*/1, /*weight=*/w1, /*mixedLeg=*/1);
12931298
}
12941299

1295-
// --- Type B: replace leg 2 → (t1, tY) ---
1300+
// --- Type B: replace leg 2 (t2 -> tY), keep t1
12961301
for (const auto& m : matches2) {
12971302
auto tY = V0s.iteratorAt(m.rowIndex);
12981303
if (!selectionV0(tY))
@@ -1309,13 +1314,15 @@ struct lambdaspincorrderived {
13091314
const float dPhi = std::fabs(RecoDecay::constrainAngle(lambda1.Phi() - lambda2.Phi(), 0.0F, harmonicDphi));
13101315
histos.fill(HIST("deltaPhiMix"), dPhi, w2);
13111316

1312-
fillHistograms2(t1.v0Status(), tY.v0Status(), lambda1, lambda2, proton1, proton2, 1, w2, 2);
1317+
// datatype=1 (ME), mixedLeg=2
1318+
fillHistograms2(t1.v0Status(), tY.v0Status(),
1319+
lambda1, lambda2, proton1, proton2,
1320+
/*datatype=*/1, /*weight=*/w2, /*mixedLeg=*/2);
13131321
}
13141322
}
13151323
}
13161324
}
1317-
1318-
PROCESS_SWITCH(lambdaspincorrderived, processMEV4, "Process data ME (5d buffer)", false);
1325+
PROCESS_SWITCH(lambdaspincorrderived, processMEV4, "Process data ME (6D buffer, both legs mixed, depth-capped)", false);
13191326
};
13201327
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
13211328
{

0 commit comments

Comments
 (0)