@@ -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