Skip to content

Commit 594d0be

Browse files
committed
Fix spin correlation definition
1 parent ef3cd2b commit 594d0be

File tree

1 file changed

+96
-3
lines changed

1 file changed

+96
-3
lines changed

PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ struct lambdaspincorrderived {
9696
Configurable<float> v0eta{"v0eta", 0.8, "Eta cut on lambda"};
9797

9898
// Event Mixing
99+
Configurable<int> cosDef{"cosDef", 1, "Defination of cos"};
99100
Configurable<int> nEvtMixing{"nEvtMixing", 10, "Number of events to mix"};
100101
ConfigurableAxis CfgVtxBins{"CfgVtxBins", {10, -10, 10}, "Mixing bins - z-vertex"};
101102
ConfigurableAxis CfgMultBins{"CfgMultBins", {8, 0.0, 80}, "Mixing bins - centrality"};
@@ -271,10 +272,102 @@ struct lambdaspincorrderived {
271272
auto proton1LambdaRF = boostLambda1ToCM(proton1pairCM);
272273
auto proton2LambdaRF = boostLambda2ToCM(proton2pairCM);
273274

274-
auto cosThetaDiff = -999.0;
275-
cosThetaDiff = proton1LambdaRF.Vect().Unit().Dot(proton2LambdaRF.Vect().Unit());
275+
TVector3 zhat(lambda1CM.Px(), lambda1CM.Py(), lambda1CM.Pz());
276+
if (zhat.Mag2() == 0)
277+
zhat = TVector3(0, 0, 1);
278+
zhat = zhat.Unit();
279+
280+
// pick a reference not collinear with ẑ (beam z works)
281+
TVector3 ref(0., 0., 1.);
282+
if (std::abs(zhat.Dot(ref)) > 0.999)
283+
ref = TVector3(1., 0., 0.);
284+
285+
// build transverse axes
286+
TVector3 xhat = (ref - (ref.Dot(zhat)) * zhat).Unit();
287+
TVector3 yhat = (zhat.Cross(xhat)).Unit();
288+
289+
// proton unit vectors in their Λ rest frames
290+
TVector3 n1(proton1LambdaRF.Px(), proton1LambdaRF.Py(), proton1LambdaRF.Pz());
291+
n1 = n1.Unit();
292+
TVector3 n2(proton2LambdaRF.Px(), proton2LambdaRF.Py(), proton2LambdaRF.Pz());
293+
n2 = n2.Unit();
294+
295+
// cosθ* (Λ2 measured along −ẑ)
296+
double c1 = n1.Dot(zhat);
297+
double c2 = -n2.Dot(zhat);
298+
299+
// sinθ*
300+
double s1 = std::sqrt(std::max(0.0, 1.0 - c1 * c1));
301+
double s2 = std::sqrt(std::max(0.0, 1.0 - c2 * c2));
302+
303+
// φ1*, φ2* in common convention (flip axes for Λ2)
304+
double phi1 = std::atan2(n1.Dot(yhat), n1.Dot(xhat));
305+
double phi2 = std::atan2(n2.Dot(-yhat), n2.Dot(-xhat));
306+
307+
// helicity spin-correlation
308+
double cosDelta = c1 * c2 + s1 * s2 * std::cos(phi1 - phi2);
309+
// clamp for safety
310+
if (cosDelta > 1.0)
311+
cosDelta = 1.0;
312+
if (cosDelta < -1.0)
313+
cosDelta = -1.0;
314+
315+
//
316+
// --- (B) Beam-based correlation (common z_B = beam; axes transported into each Λ rest frame) ---
317+
//
318+
TVector3 zB(0., 0., 1.); // beam axis in pair–CM coordinates
319+
320+
// x_B: projection of Λ1 direction onto plane ⟂ z_B; y_B completes RH basis
321+
TVector3 L1dir(lambda1CM.Px(), lambda1CM.Py(), lambda1CM.Pz());
322+
L1dir = L1dir.Unit();
323+
TVector3 xB = L1dir - (L1dir.Dot(zB)) * zB;
324+
if (xB.Mag2() < 1e-12)
325+
xB = TVector3(1., 0., 0.); // fallback if Λ1 ∥ beam
326+
xB = xB.Unit();
327+
TVector3 yB = (zB.Cross(xB)).Unit();
328+
329+
// helper to transport an axis into a Λ rest frame (from pair–CM)
330+
auto transport = [](const TVector3& v, const ROOT::Math::Boost& B) -> TVector3 {
331+
ROOT::Math::PxPyPzEVector a(v.X(), v.Y(), v.Z(), 0.0); // spacelike 4-vector (t=0)
332+
ROOT::Math::PxPyPzEVector ar = B(a); // boost into that Λ rest frame
333+
TVector3 out(ar.Px(), ar.Py(), ar.Pz());
334+
if (out.Mag2() == 0)
335+
return out;
336+
return out.Unit();
337+
};
338+
339+
// transport beam triad to each Λ rest frame
340+
TVector3 zB1 = transport(zB, boostLambda1ToCM);
341+
TVector3 xB1 = transport(xB, boostLambda1ToCM);
342+
TVector3 yB1 = transport(yB, boostLambda1ToCM);
343+
344+
TVector3 zB2 = transport(zB, boostLambda2ToCM);
345+
TVector3 xB2 = transport(xB, boostLambda2ToCM);
346+
TVector3 yB2 = transport(yB, boostLambda2ToCM);
347+
348+
// angles w.r.t. beam triad (same z_B convention for both Λ’s; no flips)
349+
double c1B = n1.Dot(zB1), c2B = n2.Dot(zB2);
350+
double s1B = std::sqrt(std::max(0.0, 1.0 - c1B * c1B));
351+
double s2B = std::sqrt(std::max(0.0, 1.0 - c2B * c2B));
352+
double phi1B = std::atan2(n1.Dot(yB1), n1.Dot(xB1));
353+
double phi2B = std::atan2(n2.Dot(yB2), n2.Dot(xB2));
354+
355+
// beam correlation
356+
double cosDeltaBeam = c1B * c2B + s1B * s2B * std::cos(phi1B - phi2B);
357+
if (cosDeltaBeam > 1.0)
358+
cosDeltaBeam = 1.0;
359+
if (cosDeltaBeam < -1.0)
360+
cosDeltaBeam = -1.0;
276361

277-
auto costhetaz1costhetaz2 = (proton1LambdaRF.Pz() * proton2LambdaRF.Pz()) / (proton1LambdaRF.P() * proton2LambdaRF.P());
362+
auto cosThetaDiff = -999.0;
363+
auto costhetaz1costhetaz2 = -999.0;
364+
if (cosDef == 0) {
365+
cosThetaDiff = proton1LambdaRF.Vect().Unit().Dot(proton2LambdaRF.Vect().Unit());
366+
costhetaz1costhetaz2 = (proton1LambdaRF.Pz() * proton2LambdaRF.Pz()) / (proton1LambdaRF.P() * proton2LambdaRF.P());
367+
} else {
368+
cosThetaDiff = cosDelta;
369+
costhetaz1costhetaz2 = cosDeltaBeam;
370+
}
278371

279372
double deltaPhi = std::abs(RecoDecay::constrainAngle(particle1Dummy.Phi(), 0.0F, harmonic) - RecoDecay::constrainAngle(particle2Dummy.Phi(), 0.0F, harmonic));
280373
double deltaEta = particle1Dummy.Eta() - particle2Dummy.Eta();

0 commit comments

Comments
 (0)