|
35 | 35 |
|
36 | 36 | #include <fairlogger/Logger.h> |
37 | 37 |
|
| 38 | +#include <algorithm> |
38 | 39 | #include <cmath> // for std::fabs |
39 | 40 | #include <deque> |
40 | 41 | #include <iostream> |
@@ -96,6 +97,7 @@ struct lambdaspincorrderived { |
96 | 97 | Configurable<float> v0eta{"v0eta", 0.8, "Eta cut on lambda"}; |
97 | 98 |
|
98 | 99 | // Event Mixing |
| 100 | + Configurable<int> cosDef{"cosDef", 1, "Defination of cos"}; |
99 | 101 | Configurable<int> nEvtMixing{"nEvtMixing", 10, "Number of events to mix"}; |
100 | 102 | ConfigurableAxis CfgVtxBins{"CfgVtxBins", {10, -10, 10}, "Mixing bins - z-vertex"}; |
101 | 103 | ConfigurableAxis CfgMultBins{"CfgMultBins", {8, 0.0, 80}, "Mixing bins - centrality"}; |
@@ -271,10 +273,102 @@ struct lambdaspincorrderived { |
271 | 273 | auto proton1LambdaRF = boostLambda1ToCM(proton1pairCM); |
272 | 274 | auto proton2LambdaRF = boostLambda2ToCM(proton2pairCM); |
273 | 275 |
|
274 | | - auto cosThetaDiff = -999.0; |
275 | | - cosThetaDiff = proton1LambdaRF.Vect().Unit().Dot(proton2LambdaRF.Vect().Unit()); |
| 276 | + TVector3 zhat(lambda1CM.Px(), lambda1CM.Py(), lambda1CM.Pz()); |
| 277 | + if (zhat.Mag2() == 0) |
| 278 | + zhat = TVector3(0, 0, 1); |
| 279 | + zhat = zhat.Unit(); |
| 280 | + |
| 281 | + // pick a reference not collinear with ẑ (beam z works) |
| 282 | + TVector3 ref(0., 0., 1.); |
| 283 | + if (std::abs(zhat.Dot(ref)) > 0.999) |
| 284 | + ref = TVector3(1., 0., 0.); |
| 285 | + |
| 286 | + // build transverse axes |
| 287 | + TVector3 xhat = (ref - (ref.Dot(zhat)) * zhat).Unit(); |
| 288 | + TVector3 yhat = (zhat.Cross(xhat)).Unit(); |
| 289 | + |
| 290 | + // proton unit vectors in their Λ rest frames |
| 291 | + TVector3 n1(proton1LambdaRF.Px(), proton1LambdaRF.Py(), proton1LambdaRF.Pz()); |
| 292 | + n1 = n1.Unit(); |
| 293 | + TVector3 n2(proton2LambdaRF.Px(), proton2LambdaRF.Py(), proton2LambdaRF.Pz()); |
| 294 | + n2 = n2.Unit(); |
| 295 | + |
| 296 | + // cosθ* (Λ2 measured along −ẑ) |
| 297 | + double c1 = n1.Dot(zhat); |
| 298 | + double c2 = -n2.Dot(zhat); |
| 299 | + |
| 300 | + // sinθ* |
| 301 | + double s1 = std::sqrt(std::max(0.0, 1.0 - c1 * c1)); |
| 302 | + double s2 = std::sqrt(std::max(0.0, 1.0 - c2 * c2)); |
| 303 | + |
| 304 | + // φ1*, φ2* in common convention (flip axes for Λ2) |
| 305 | + double phi1 = std::atan2(n1.Dot(yhat), n1.Dot(xhat)); |
| 306 | + double phi2 = std::atan2(n2.Dot(-yhat), n2.Dot(-xhat)); |
| 307 | + |
| 308 | + // helicity spin-correlation |
| 309 | + double cosDelta = c1 * c2 + s1 * s2 * std::cos(phi1 - phi2); |
| 310 | + // clamp for safety |
| 311 | + if (cosDelta > 1.0) |
| 312 | + cosDelta = 1.0; |
| 313 | + if (cosDelta < -1.0) |
| 314 | + cosDelta = -1.0; |
| 315 | + |
| 316 | + // |
| 317 | + // --- (B) Beam-based correlation (common z_B = beam; axes transported into each Λ rest frame) --- |
| 318 | + // |
| 319 | + TVector3 zB(0., 0., 1.); // beam axis in pair–CM coordinates |
| 320 | + |
| 321 | + // x_B: projection of Λ1 direction onto plane ⟂ z_B; y_B completes RH basis |
| 322 | + TVector3 L1dir(lambda1CM.Px(), lambda1CM.Py(), lambda1CM.Pz()); |
| 323 | + L1dir = L1dir.Unit(); |
| 324 | + TVector3 xB = L1dir - (L1dir.Dot(zB)) * zB; |
| 325 | + if (xB.Mag2() < 1e-12) |
| 326 | + xB = TVector3(1., 0., 0.); // fallback if Λ1 ∥ beam |
| 327 | + xB = xB.Unit(); |
| 328 | + TVector3 yB = (zB.Cross(xB)).Unit(); |
| 329 | + |
| 330 | + // helper to transport an axis into a Λ rest frame (from pair–CM) |
| 331 | + auto transport = [](const TVector3& v, const ROOT::Math::Boost& B) -> TVector3 { |
| 332 | + ROOT::Math::PxPyPzEVector a(v.X(), v.Y(), v.Z(), 0.0); // spacelike 4-vector (t=0) |
| 333 | + ROOT::Math::PxPyPzEVector ar = B(a); // boost into that Λ rest frame |
| 334 | + TVector3 out(ar.Px(), ar.Py(), ar.Pz()); |
| 335 | + if (out.Mag2() == 0) |
| 336 | + return out; |
| 337 | + return out.Unit(); |
| 338 | + }; |
| 339 | + |
| 340 | + // transport beam triad to each Λ rest frame |
| 341 | + TVector3 zB1 = transport(zB, boostLambda1ToCM); |
| 342 | + TVector3 xB1 = transport(xB, boostLambda1ToCM); |
| 343 | + TVector3 yB1 = transport(yB, boostLambda1ToCM); |
| 344 | + |
| 345 | + TVector3 zB2 = transport(zB, boostLambda2ToCM); |
| 346 | + TVector3 xB2 = transport(xB, boostLambda2ToCM); |
| 347 | + TVector3 yB2 = transport(yB, boostLambda2ToCM); |
| 348 | + |
| 349 | + // angles w.r.t. beam triad (same z_B convention for both Λ’s; no flips) |
| 350 | + double c1B = n1.Dot(zB1), c2B = n2.Dot(zB2); |
| 351 | + double s1B = std::sqrt(std::max(0.0, 1.0 - c1B * c1B)); |
| 352 | + double s2B = std::sqrt(std::max(0.0, 1.0 - c2B * c2B)); |
| 353 | + double phi1B = std::atan2(n1.Dot(yB1), n1.Dot(xB1)); |
| 354 | + double phi2B = std::atan2(n2.Dot(yB2), n2.Dot(xB2)); |
| 355 | + |
| 356 | + // beam correlation |
| 357 | + double cosDeltaBeam = c1B * c2B + s1B * s2B * std::cos(phi1B - phi2B); |
| 358 | + if (cosDeltaBeam > 1.0) |
| 359 | + cosDeltaBeam = 1.0; |
| 360 | + if (cosDeltaBeam < -1.0) |
| 361 | + cosDeltaBeam = -1.0; |
276 | 362 |
|
277 | | - auto costhetaz1costhetaz2 = (proton1LambdaRF.Pz() * proton2LambdaRF.Pz()) / (proton1LambdaRF.P() * proton2LambdaRF.P()); |
| 363 | + auto cosThetaDiff = -999.0; |
| 364 | + auto costhetaz1costhetaz2 = -999.0; |
| 365 | + if (cosDef == 0) { |
| 366 | + cosThetaDiff = proton1LambdaRF.Vect().Unit().Dot(proton2LambdaRF.Vect().Unit()); |
| 367 | + costhetaz1costhetaz2 = (proton1LambdaRF.Pz() * proton2LambdaRF.Pz()) / (proton1LambdaRF.P() * proton2LambdaRF.P()); |
| 368 | + } else { |
| 369 | + cosThetaDiff = cosDelta; |
| 370 | + costhetaz1costhetaz2 = cosDeltaBeam; |
| 371 | + } |
278 | 372 |
|
279 | 373 | double deltaPhi = std::abs(RecoDecay::constrainAngle(particle1Dummy.Phi(), 0.0F, harmonic) - RecoDecay::constrainAngle(particle2Dummy.Phi(), 0.0F, harmonic)); |
280 | 374 | double deltaEta = particle1Dummy.Eta() - particle2Dummy.Eta(); |
|
0 commit comments