2828#include " Framework/AnalysisTask.h"
2929#include " Framework/runDataProcessing.h"
3030
31- #include " TPDGCode.h"
32-
31+ #include < array>
3332#include < string>
3433#include < vector>
3534
@@ -76,6 +75,9 @@ DECLARE_SOA_COLUMN(Eta, eta, float);
7675DECLARE_SOA_COLUMN (Phi, phi, float );
7776DECLARE_SOA_COLUMN (Rap, rap, float );
7877DECLARE_SOA_COLUMN (Mass, mass, float );
78+ DECLARE_SOA_COLUMN (PrPx, prPx, float );
79+ DECLARE_SOA_COLUMN (PrPy, prPy, float );
80+ DECLARE_SOA_COLUMN (PrPz, prPz, float );
7981DECLARE_SOA_COLUMN (PosTrackId, posTrackId, int64_t );
8082DECLARE_SOA_COLUMN (NegTrackId, negTrackId, int64_t );
8183DECLARE_SOA_COLUMN (CosPA, cosPA, float );
@@ -94,6 +96,9 @@ DECLARE_SOA_TABLE(LambdaTracks, "AOD", "LAMBDATRACKS", o2::soa::Index<>,
9496 lambdatrack::Phi,
9597 lambdatrack::Rap,
9698 lambdatrack::Mass,
99+ lambdatrack::PrPx,
100+ lambdatrack::PrPy,
101+ lambdatrack::PrPz,
97102 lambdatrack::PosTrackId,
98103 lambdatrack::NegTrackId,
99104 lambdatrack::CosPA,
@@ -130,6 +135,9 @@ DECLARE_SOA_TABLE(LambdaMcGenTracks, "AOD", "LMCGENTRACKS", o2::soa::Index<>,
130135 lambdatrack::Phi,
131136 lambdatrack::Rap,
132137 lambdatrack::Mass,
138+ lambdatrack::PrPx,
139+ lambdatrack::PrPy,
140+ lambdatrack::PrPz,
133141 lambdatrack::PosTrackId,
134142 lambdatrack::NegTrackId,
135143 lambdatrack::V0Type,
@@ -178,7 +186,7 @@ enum TrackLabels {
178186
179187enum CentEstType {
180188 kCentFT0M = 0 ,
181- kCentFV0A
189+ kCentFT0C
182190};
183191
184192enum RunType {
@@ -238,7 +246,7 @@ struct LambdaTableProducer {
238246 Produces<aod::LambdaMcGenTracks> lambdaMCGenTrackTable;
239247
240248 // Collisions
241- Configurable<int > cCentEstimator{" cCentEstimator" , 0 , " Centrality Estimator : 0-FT0M, 1-FV0A " };
249+ Configurable<int > cCentEstimator{" cCentEstimator" , 0 , " Centrality Estimator : 0-FT0M, 1-FT0C " };
242250 Configurable<float > cMinZVtx{" cMinZVtx" , -10.0 , " Min VtxZ cut" };
243251 Configurable<float > cMaxZVtx{" cMaxZVtx" , 10.0 , " Max VtxZ cut" };
244252 Configurable<float > cMinMult{" cMinMult" , 0 ., " Minumum Multiplicity" };
@@ -491,8 +499,8 @@ struct LambdaTableProducer {
491499 // select centrality estimator
492500 if (cCentEstimator == kCentFT0M ) {
493501 cent = col.centFT0M ();
494- } else if (cCentEstimator == kCentFV0A ) {
495- cent = col.centFV0A ();
502+ } else if (cCentEstimator == kCentFT0C ) {
503+ cent = col.centFT0C ();
496504 }
497505 if (cSel8Trig && !col.sel8 ()) {
498506 return false ;
@@ -989,6 +997,7 @@ struct LambdaTableProducer {
989997 ParticleType v0Type = kLambda ;
990998 PrmScdType v0PrmScdType = kPrimary ;
991999 float mass = 0 ., corr_fact = 1 .;
1000+ float prPx = 0 ., prPy = 0 ., prPz = 0 .;
9921001
9931002 for (auto const & v0 : v0tracks) {
9941003 // check for corresponding MCGen Particle
@@ -1072,18 +1081,27 @@ struct LambdaTableProducer {
10721081
10731082 // fill lambda qa
10741083 if (v0Type == kLambda ) {
1084+ // Assign proton Eta Phi
1085+ prPx = v0.template posTrack_as <T>().px ();
1086+ prPy = v0.template posTrack_as <T>().py ();
1087+ prPz = v0.template posTrack_as <T>().pz ();
10751088 histos.fill (HIST (" Tracks/h1f_lambda_pt_vs_invm" ), mass, v0.pt ());
10761089 fillLambdaQAHistos<kLambda >(collision, v0, tracks);
10771090 fillKinematicHists<kRec , kLambda >(v0.pt (), v0.eta (), v0.yLambda (), v0.phi ());
10781091 } else {
1092+ // Assign proton Eta Phi
1093+ prPx = v0.template negTrack_as <T>().px ();
1094+ prPy = v0.template negTrack_as <T>().py ();
1095+ prPz = v0.template negTrack_as <T>().pz ();
10791096 histos.fill (HIST (" Tracks/h1f_antilambda_pt_vs_invm" ), mass, v0.pt ());
10801097 fillLambdaQAHistos<kAntiLambda >(collision, v0, tracks);
10811098 fillKinematicHists<kRec , kAntiLambda >(v0.pt (), v0.eta (), v0.yLambda (), v0.phi ());
10821099 }
10831100
10841101 // Fill Lambda/AntiLambda Table
10851102 lambdaTrackTable (lambdaCollisionTable.lastIndex (), v0.px (), v0.py (), v0.pz (),
1086- pt, eta, phi, rap, mass, v0.template posTrack_as <T>().index (), v0.template negTrack_as <T>().index (),
1103+ pt, eta, phi, rap, mass, prPx, prPy, prPz,
1104+ v0.template posTrack_as <T>().index (), v0.template negTrack_as <T>().index (),
10871105 v0.v0cosPA (), v0.dcaV0daughters (), (int8_t )v0Type, v0PrmScdType, corr_fact);
10881106 }
10891107 }
@@ -1099,6 +1117,7 @@ struct LambdaTableProducer {
10991117 ParticleType v0Type = kLambda ;
11001118 PrmScdType v0PrmScdType = kPrimary ;
11011119 float rap = 0 .;
1120+ float prPx = 0 ., prPy = 0 ., prPz = 0 .;
11021121
11031122 for (auto const & mcpart : mcParticles) {
11041123 // check for Lambda first
@@ -1139,13 +1158,17 @@ struct LambdaTableProducer {
11391158 auto dautracks = mcpart.template daughters_as <aod::McParticles>();
11401159 std::vector<int > daughterPDGs, daughterIDs;
11411160 std::vector<float > vDauPt, vDauEta, vDauRap, vDauPhi;
1161+ std::vector<float > vDauPx, vDauPy, vDauPz;
11421162 for (auto const & dautrack : dautracks) {
11431163 daughterPDGs.push_back (dautrack.pdgCode ());
11441164 daughterIDs.push_back (dautrack.globalIndex ());
11451165 vDauPt.push_back (dautrack.pt ());
11461166 vDauEta.push_back (dautrack.eta ());
11471167 vDauRap.push_back (dautrack.y ());
11481168 vDauPhi.push_back (dautrack.phi ());
1169+ vDauPx.push_back (dautrack.px ());
1170+ vDauPy.push_back (dautrack.py ());
1171+ vDauPz.push_back (dautrack.pz ());
11491172 }
11501173 if (cGenDecayChannel) { // check decay channel
11511174 if (v0Type == kLambda ) {
@@ -1162,6 +1185,10 @@ struct LambdaTableProducer {
11621185 histos.fill (HIST (" Tracks/h1f_tracks_info" ), kGenLambdaToPrPi );
11631186
11641187 if (v0Type == kLambda ) {
1188+ // Assign proton p-vec
1189+ prPx = vDauPx[0 ];
1190+ prPy = vDauPy[0 ];
1191+ prPz = vDauPz[0 ];
11651192 histos.fill (HIST (" McGen/h1f_lambda_daughter_PDG" ), daughterPDGs[0 ]);
11661193 histos.fill (HIST (" McGen/h1f_lambda_daughter_PDG" ), daughterPDGs[1 ]);
11671194 histos.fill (HIST (" McGen/h1f_lambda_daughter_PDG" ), mcpart.pdgCode ());
@@ -1175,6 +1202,10 @@ struct LambdaTableProducer {
11751202 histos.fill (HIST (" McGen/Lambda/Pion/hPhi" ), vDauPhi[1 ]);
11761203 fillKinematicHists<kGen , kLambda >(mcpart.pt (), mcpart.eta (), mcpart.y (), mcpart.phi ());
11771204 } else {
1205+ // Assign anti-proton p-vec
1206+ prPx = vDauPx[1 ];
1207+ prPy = vDauPy[1 ];
1208+ prPz = vDauPz[1 ];
11781209 histos.fill (HIST (" McGen/h1f_antilambda_daughter_PDG" ), daughterPDGs[0 ]);
11791210 histos.fill (HIST (" McGen/h1f_antilambda_daughter_PDG" ), daughterPDGs[1 ]);
11801211 histos.fill (HIST (" McGen/h1f_antilambda_daughter_PDG" ), mcpart.pdgCode ());
@@ -1191,7 +1222,7 @@ struct LambdaTableProducer {
11911222
11921223 // Fill Lambda McGen Table
11931224 lambdaMCGenTrackTable (lambdaMCGenCollisionTable.lastIndex (), mcpart.px (), mcpart.py (), mcpart.pz (),
1194- mcpart.pt (), mcpart.eta (), mcpart.phi (), mcpart.y (), RecoDecay::m (mcpart.p (), mcpart.e ()),
1225+ mcpart.pt (), mcpart.eta (), mcpart.phi (), mcpart.y (), RecoDecay::m (mcpart.p (), mcpart.e ()), prPx, prPy, prPz,
11951226 daughterIDs[0 ], daughterIDs[1 ], (int8_t )v0Type, -999 ., -999 ., v0PrmScdType, 1 .);
11961227 }
11971228 }
@@ -1223,7 +1254,7 @@ struct LambdaTableProducer {
12231254 SliceCache cache;
12241255 Preslice<soa::Join<aod::V0Datas, aod::McV0Labels>> perCollision = aod::v0data::collisionId;
12251256
1226- using CollisionsRun3 = soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Ms, aod::CentFV0As , aod::PVMults>;
1257+ using CollisionsRun3 = soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Ms, aod::CentFT0Cs , aod::PVMults>;
12271258 using CollisionsRun2 = soa::Join<aod::Collisions, aod::EvSels, aod::CentRun2V0Ms, aod::PVMults>;
12281259 using Tracks = soa::Join<aod::Tracks, aod::TrackSelection, aod::TracksExtra, aod::TracksDCA, aod::pidTPCPi, aod::pidTPCPr, aod::TrackCompColls>;
12291260 using TracksRun2 = soa::Join<aod::Tracks, aod::TrackSelection, aod::TracksExtra, aod::TracksDCA, aod::pidTPCPi, aod::pidTPCPr>;
@@ -1453,6 +1484,173 @@ struct LambdaTracksExtProducer {
14531484 }
14541485};
14551486
1487+ struct LambdaSpinCorrelation {
1488+ // Global Configurables
1489+ Configurable<int > cNPtBins{" cNPtBins" , 30 , " N pT Bins" };
1490+ Configurable<float > cMinPt{" cMinPt" , 0.5 , " pT Min" };
1491+ Configurable<float > cMaxPt{" cMaxPt" , 3.5 , " pT Max" };
1492+ Configurable<int > cNRapBins{" cNRapBins" , 20 , " N Rapidity Bins" };
1493+ Configurable<float > cMinRap{" cMinRap" , -0.5 , " Minimum Rapidity" };
1494+ Configurable<float > cMaxRap{" cMaxRap" , 0.5 , " Maximum Rapidity" };
1495+ Configurable<int > cNPhiBins{" cNPhiBins" , 36 , " N Phi Bins" };
1496+ Configurable<bool > cAnaPairs{" cAnaPairs" , false , " Analyze Pairs Flag" };
1497+ Configurable<bool > cInvBoostFlag{" cInvBoostFlag" , true , " Inverse Boost Flag" };
1498+
1499+ // Centrality Axis
1500+ ConfigurableAxis cMultBins{" cMultBins" , {VARIABLE_WIDTH, 0 .0f , 10 .0f , 30 .0f , 50 .f , 80 .0f , 100 .f }, " Variable Mult-Bins" };
1501+
1502+ // Histogram Registry.
1503+ HistogramRegistry histos{" histos" , {}, OutputObjHandlingPolicy::AnalysisObject};
1504+
1505+ // Global variables
1506+ float cent = 0 .;
1507+
1508+ void init (InitContext const &)
1509+ {
1510+ const AxisSpec axisCheck (1 , 0 , 1 , " " );
1511+ const AxisSpec axisPosZ (220 , -11 , 11 , " V_{z} (cm)" );
1512+ const AxisSpec axisCent (cMultBins, " FT0M (%)" );
1513+ const AxisSpec axisChMult (200 , 0 , 200 , " N_{ch}" );
1514+ const AxisSpec axisMult (10 , 0 , 10 , " N_{#Lambda}" );
1515+ const AxisSpec axisMass (100 , 1.06 , 1.16 , " M_{#Lambda} (GeV/#it{c}^{2})" );
1516+ const AxisSpec axisPt (cNPtBins, cMinPt, cMaxPt, " p_{T} (GeV/#it{c})" );
1517+ const AxisSpec axisEta (cNRapBins, cMinRap, cMaxRap, " #eta" );
1518+ const AxisSpec axisRap (cNRapBins, cMinRap, cMaxRap, " y" );
1519+ const AxisSpec axisPhi (cNPhiBins, 0 ., TwoPI, " #varphi (rad)" );
1520+ const AxisSpec axisDPhi (cNPhiBins, -PI, PI, " #Delta#varphi" );
1521+
1522+ // Single and Two Particle Densities
1523+ // 1D Histograms
1524+ histos.add (" Reco/h2f_n2_mass_LaPLaM" , " m_{inv}^{#Lambda} vs m_{inv}^{#bar{#Lambda}}" , kTH2F , {axisMass, axisMass});
1525+ histos.add (" Reco/h2f_n2_mass_LaPLaP" , " m_{inv}^{#Lambda} vs m_{inv}^{#Lambda}" , kTH2F , {axisMass, axisMass});
1526+ histos.add (" Reco/h2f_n2_mass_LaMLaM" , " m_{inv}^{#bar{#Lambda}} vs m_{inv}^{#bar{#Lambda}}" , kTH2F , {axisMass, axisMass});
1527+
1528+ // rho1 for C2
1529+ histos.add (" RecoCorr/h2f_n1_phi_LaP" , " #rho_{1}^{#Lambda}" , kTH2F , {axisCent, axisPhi});
1530+ histos.add (" RecoCorr/h2f_n1_phi_LaM" , " #rho_{1}^{#bar{#Lambda}}" , kTH2F , {axisCent, axisPhi});
1531+
1532+ // rho2 for C2
1533+ histos.add (" RecoCorr/h2f_n2_dphi_LaPLaM" , " #rho_{2}^{#Lambda#bar{#Lambda}}" , kTH2F , {axisCent, axisDPhi});
1534+ histos.add (" RecoCorr/h2f_n2_dphi_LaPLaP" , " #rho_{2}^{#Lambda#Lambda}" , kTH2F , {axisCent, axisDPhi});
1535+ histos.add (" RecoCorr/h2f_n2_dphi_LaMLaM" , " #rho_{2}^{#bar{#Lambda}#bar{#Lambda}}" , kTH2F , {axisCent, axisDPhi});
1536+ histos.add (" RecoCorr/h2f_n2_phiphi_LaPLaM" , " #rho_{2}^{#Lambda#bar{#Lambda}}" , kTH3F , {axisCent, axisPhi, axisPhi});
1537+ histos.add (" RecoCorr/h2f_n2_phiphi_LaPLaP" , " #rho_{2}^{#Lambda#Lambda}" , kTH3F , {axisCent, axisPhi, axisPhi});
1538+ histos.add (" RecoCorr/h2f_n2_phiphi_LaMLaM" , " #rho_{2}^{#bar{#Lambda}#bar{#Lambda}}" , kTH3F , {axisCent, axisPhi, axisPhi});
1539+ }
1540+
1541+ void getBoostVector (std::array<float , 4 > const & p, std::array<float , 3 >& v, bool inverseBoostFlag = true )
1542+ {
1543+ int n = p.size ();
1544+ for (int i = 0 ; i < n - 1 ; ++i) {
1545+ if (inverseBoostFlag) {
1546+ v[i] = -p[i] / RecoDecay::e (p[0 ], p[1 ], p[2 ], p[3 ]);
1547+ } else {
1548+ v[i] = p[i] / RecoDecay::e (p[0 ], p[1 ], p[2 ], p[3 ]);
1549+ }
1550+ }
1551+ }
1552+
1553+ void boost (std::array<float , 4 >& p, std::array<float , 3 > const & b)
1554+ {
1555+ float e = RecoDecay::e (p[0 ], p[1 ], p[2 ], p[3 ]);
1556+ float b2 = b[0 ] * b[0 ] + b[1 ] * b[1 ] + b[2 ] * b[2 ];
1557+ float gamma = 1 . / std::sqrt (1 - b2);
1558+ float bp = b[0 ] * p[0 ] + b[1 ] * p[1 ] + b[2 ] * p[2 ];
1559+ float gamma2 = b2 > 0 ? (gamma - 1 .) / b2 : 0 .;
1560+
1561+ p[0 ] = p[0 ] + gamma2 * bp * b[0 ] + gamma * b[0 ] * e;
1562+ p[1 ] = p[1 ] + gamma2 * bp * b[1 ] + gamma * b[1 ] * e;
1563+ p[2 ] = p[2 ] + gamma2 * bp * b[2 ] + gamma * b[2 ] * e;
1564+ }
1565+
1566+ template <ParticlePairType part_pair, typename U>
1567+ void fillPairHistos (U& p1, U& p2)
1568+ {
1569+ static constexpr std::string_view SubDirHist[] = {" LaPLaM" , " LaPLaP" , " LaMLaM" };
1570+
1571+ // Fill lambda pair mass
1572+ histos.fill (HIST (" Reco/h2f_n2_mass_" ) + HIST (SubDirHist[part_pair]), p1.mass (), p2.mass ());
1573+
1574+ // Get Lambda-Proton four-momentum
1575+ std::array<float , 4 > l1 = {p1.px (), p1.py (), p1.pz (), MassLambda0};
1576+ std::array<float , 4 > l2 = {p2.px (), p2.py (), p2.pz (), MassLambda0};
1577+ std::array<float , 4 > pr1 = {p1.prPx (), p1.prPy (), p1.prPz (), MassProton};
1578+ std::array<float , 4 > pr2 = {p2.prPx (), p2.prPy (), p2.prPz (), MassProton};
1579+ std::array<float , 3 > v1, v2;
1580+ getBoostVector (l1, v1, cInvBoostFlag);
1581+ getBoostVector (l2, v2, cInvBoostFlag);
1582+ boost (pr1, v1);
1583+ boost (pr2, v2);
1584+
1585+ // Fill pair density
1586+ histos.fill (HIST (" RecoCorr/h2f_n2_phiphi_" ) + HIST (SubDirHist[part_pair]), cent, RecoDecay::constrainAngle (RecoDecay::phi (pr1)), RecoDecay::phi (pr2));
1587+ histos.fill (HIST (" RecoCorr/h2f_n2_dphi_" ) + HIST (SubDirHist[part_pair]), cent, RecoDecay::constrainAngle (RecoDecay::phi (pr1) - RecoDecay::phi (pr2), -PI));
1588+ }
1589+
1590+ template <ParticleType part, typename T>
1591+ void analyzeSingles (T const & tracks)
1592+ {
1593+ static constexpr std::string_view SubDirHist[] = {" LaP" , " LaM" };
1594+ for (auto const & track : tracks) {
1595+ // Get four-momentum of lambda
1596+ std::array<float , 4 > l = {MassLambda0, track.px (), track.py (), track.pz ()};
1597+ std::array<float , 4 > p = {MassProton, track.prPx (), track.prPy (), track.prPz ()};
1598+ std::array<float , 3 > v;
1599+ getBoostVector (l, v, cInvBoostFlag);
1600+ boost (p, v);
1601+
1602+ // Fill single histograms
1603+ histos.fill (HIST (" RecoCorr/h2f_n1_phi_" ) + HIST (SubDirHist[part]), cent, RecoDecay::constrainAngle (RecoDecay::phi (p)));
1604+ }
1605+ }
1606+
1607+ template <ParticlePairType partpair, bool samelambda, typename T>
1608+ void analyzePairs (T const & trks_1, T const & trks_2)
1609+ {
1610+ for (auto const & trk_1 : trks_1) {
1611+ for (auto const & trk_2 : trks_2) {
1612+ // check for same index for Lambda-Lambda / AntiLambda-AntiLambda
1613+ if (samelambda && ((trk_1.index () == trk_2.index ()))) {
1614+ continue ;
1615+ }
1616+ fillPairHistos<partpair>(trk_1, trk_2);
1617+ }
1618+ }
1619+ }
1620+
1621+ // Initialize tables
1622+ using LambdaCollisions = aod::LambdaCollisions;
1623+ using LambdaTracks = soa::Join<aod::LambdaTracks, aod::LambdaTracksExt>;
1624+
1625+ SliceCache cache;
1626+ Partition<LambdaTracks> partLambdaTracks = (aod::lambdatrack::v0Type == (int8_t )kLambda ) && (aod::lambdatrackext::trueLambdaFlag == true ) && (aod::lambdatrack::v0PrmScd == (int8_t )kPrimary );
1627+ Partition<LambdaTracks> partAntiLambdaTracks = (aod::lambdatrack::v0Type == (int8_t )kAntiLambda ) && (aod::lambdatrackext::trueLambdaFlag == true ) && (aod::lambdatrack::v0PrmScd == (int8_t )kPrimary );
1628+
1629+ void processDummy (LambdaCollisions::iterator const &) {}
1630+
1631+ PROCESS_SWITCH (LambdaSpinCorrelation, processDummy, " Dummy process" , true );
1632+
1633+ void processDataReco (LambdaCollisions::iterator const & collision, LambdaTracks const &)
1634+ {
1635+ // assign centrality
1636+ cent = collision.cent ();
1637+
1638+ auto lambdaTracks = partLambdaTracks->sliceByCached (aod::lambdatrack::lambdaCollisionId, collision.globalIndex (), cache);
1639+ auto antiLambdaTracks = partAntiLambdaTracks->sliceByCached (aod::lambdatrack::lambdaCollisionId, collision.globalIndex (), cache);
1640+
1641+ analyzeSingles<kLambda >(lambdaTracks);
1642+ analyzeSingles<kAntiLambda >(antiLambdaTracks);
1643+
1644+ if (cAnaPairs) {
1645+ analyzePairs<kLambdaAntiLambda , false >(lambdaTracks, antiLambdaTracks);
1646+ analyzePairs<kLambdaLambda , true >(lambdaTracks, lambdaTracks);
1647+ analyzePairs<kAntiLambdaAntiLambda , true >(antiLambdaTracks, antiLambdaTracks);
1648+ }
1649+ }
1650+
1651+ PROCESS_SWITCH (LambdaSpinCorrelation, processDataReco, " Process for Data and MCReco" , false );
1652+ };
1653+
14561654struct LambdaR2Correlation {
14571655 // Global Configurables
14581656 Configurable<int > cNPtBins{" cNPtBins" , 34 , " N pT Bins" };
@@ -1797,5 +1995,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
17971995 return WorkflowSpec{
17981996 adaptAnalysisTask<LambdaTableProducer>(cfgc),
17991997 adaptAnalysisTask<LambdaTracksExtProducer>(cfgc),
1998+ adaptAnalysisTask<LambdaSpinCorrelation>(cfgc),
18001999 adaptAnalysisTask<LambdaR2Correlation>(cfgc)};
18012000}
0 commit comments