1+ // Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+ // See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+ // All rights not expressly granted are reserved.
4+ //
5+ // This software is distributed under the terms of the GNU General Public
6+ // License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+ //
8+ // In applying this license CERN does not waive the privileges and immunities
9+ // granted to it by virtue of its status as an Intergovernmental Organization
10+ // or submit itself to any jurisdiction.
11+ //
12+ // / \file lambdaJetPolarizationIonsDerived.cxx
13+ // / \brief Lambda and antiLambda polarization analysis task using derived data
14+ // /
15+ // / \author Cicero Domenico Muncinelli <cicero.domenico.muncinelli@cern.ch>, Campinas State University
16+ //
17+ // Jet Polarization Ions task -- Derived data
18+ // ================
19+ //
20+ // This code loops over custom derived data tables defined on
21+ // lambdaJetPolarizationIons.h (JetsRing, LambdaLikeV0sRing).
22+ // From this derived data, calculates polarization on an EbE
23+ // basis.
24+ //
25+ //
26+ // Comments, questions, complaints, suggestions?
27+ // Please write to:
28+ // cicero.domenico.muncinelli@cern.ch
29+ //
30+
31+ #include < Framework/ASoA.h>
32+ #include < Framework/ASoAHelpers.h>
33+ #include < Framework/AnalysisDataModel.h>
34+ #include < Framework/AnalysisTask.h>
35+ #include < Framework/Logger.h>
36+ #include < Framework/runDataProcessing.h>
37+
38+ // Custom data model:
39+ #include " PWGLF/DataModel/lambdaJetPolarizationIons.h"
40+
41+ #include < cmath>
42+ #include < map>
43+ #include < string>
44+ #include < vector>
45+
46+ // #include <TLorentzVector.h>
47+ // #include <TVector3.h>
48+ // New recommended format:
49+ #include < Math/Vector3D.h>
50+ #include < Math/Vector4D.h>
51+
52+ using namespace o2 ;
53+ using namespace o2 ::framework;
54+ using namespace o2 ::framework::expressions;
55+ using namespace ROOT ::Math;
56+ // using namespace o2::aod::lambdajetpol; // Used it explicitly along the code for clarity
57+ struct lambdaJetPolarizationIonsDerived {
58+ const double protonMass = o2::constants::physics::MassProton; // Assumes particle identification for daughter is perfect
59+ const double lambdaWeakDecayConstant = 0.747 ; // Fixed as a constant for this analysis.
60+
61+
62+
63+
64+
65+
66+ void processPolarizationData (aod::RingCollisions const & collisions, aod::RingJets const & jets, aod::RingLambdaLikeV0s const & v0s){
67+
68+ for (auto const & collision : collisions) {
69+ const auto collId = collision.collIdx ();
70+ const double centrality = collision.centrality ();
71+
72+ // Slice jets and V0s belonging to this collision
73+ auto jetsInColl = jets.sliceBy (o2::aod::lambdajetpol::collIdx, collId);
74+ auto v0sInColl = v0s.sliceBy (o2::aod::lambdajetpol::collIdx, collId);
75+
76+ // Check if there is at least one V0 and one jet in the collision:
77+ // (in the way I fill the table, there is always at least one V0 in
78+ // the stored collision, but the jets table can not be filled for
79+ // that collision, and a collision may not be filled when the jets
80+ // table is. Be mindful of that!)
81+ if (jetsInColl.empty () || v0sInColl.empty ()) continue ;
82+
83+ // Get leading jet:
84+ double leadingJetPt = -1 ;
85+ o2::aod::RingJets::iterator leadingJet;
86+ for (auto const & jet : jetsInColl) {
87+ const auto jetpt = jet.jetPt ();
88+ if (jetpt > leadingJetPt){
89+ leadingJetPt = jetpt;
90+ leadingJet = jet;
91+ }
92+ }
93+
94+ // Now you can use:
95+ const double leadingJetEta = leadingJet.jetEta ();
96+ const double leadingJetPhi = leadingJet.jetPhi ();
97+
98+ // Convert to 3-vector components for inner product:
99+ const double jetPx = leadingJetPt * std::cos (leadingJetPhi);
100+ const double jetPy = leadingJetPt * std::sin (leadingJetPhi);
101+ const double jetPz = leadingJetPt * std::sinh (leadingJetEta);
102+
103+ // TODO: add centrality selection procedure and options (one configurable for no centrality separation at all too!)
104+ // TODO: add Lambda candidate selection. Think of a statistical method like signal extraction (if possible) for ring polarization
105+ // TODO: add calculations with second to leading jet too.
106+ // TODO: Add calculations with leading particle
107+ for (auto const & v0 : v0sInColl) {
108+ const double v0pt = v0.V0Pt ();
109+ const double v0eta = v0.v0Eta ();
110+ const double v0phi = v0.Phi ();
111+
112+ double v0LambdaMass;
113+ double protonLikePt;
114+ double protonLikeEta;
115+ double protonLikePhi;
116+ if (isLambda){
117+ v0LambdaMass = v0.MassLambda ();
118+ protonLikePt = v0.PosPt ();
119+ protonLikeEta = v0.PosEta ();
120+ protonLikePhi = v0.PosPhi ();
121+ }
122+ // (TODO: implement AntiLambda polarization)
123+ // if (isAntiLambda){
124+ // }
125+
126+ const double lambdaPx = v0pt * std::cos (v0phi);
127+ const double lambdaPy = v0pt * std::sin (v0phi);
128+ const double lambdaPz = v0pt * std::sinh (v0eta);
129+ const double lambdaMomentumSquared = lambdaPx*lambdaPx + lambdaPy*lambdaPy + lambdaPz*lambdaPz;
130+ const double lambdaE = std::sqrt (v0LambdaMass*v0LambdaMass + lambdaMomentumSquared);
131+ // const double lambdaRapidity = 0.5 * std::log((lambdaE + lambdaPz) / (lambdaE - lambdaPz)); // For extra selection criteria later
132+ const double lambdaRapidity = std::atanh (lambdaPz / lambdaE); // More numerically stable
133+
134+ const double protonPx = protonLikePt * std::cos (protonLikePhi);
135+ const double protonPy = protonLikePt * std::sin (protonLikePhi);
136+ const double protonPz = protonLikePt * std::sinh (protonLikeEta);
137+ const double protonMomentumSquared = protonPx*protonPx + protonPy*protonPy + protonPz*protonPz;
138+ const double protonE = std::sqrt (protonMass*protonMass + protonMomentumSquared);
139+
140+ TLorentzVector lambdaLike4Vec (lambdaPx, lambdaPy, lambdaPz, lambdaE);
141+ TLorentzVector protonLike4Vec (protonPx, protonPy, protonPz, protonE);
142+
143+ // Boosting proton into lambda frame:
144+ TVector3 betaInverse = -lambdaLike4Vec.BoostVector (); // Boost trivector that goes from laboratory frame to the rest frame
145+ TLorentzVector protonLike4VecStar = protonLike4Vec;
146+ protonLike4VecStar.Boost (betaInverse);
147+
148+ TVector3 protonLikeStarUnitVec = (protonLike4VecStar.Vect ()).Unit ();
149+ TVector3 jetUnitVec = (TVector3 (jetPx, jetPy, jetPz)).Unit ();
150+ TVector3 lambda3Vec = TVector3 (lambdaPx, lambdaPy, lambdaPz);
151+
152+ // Calculating inner product:
153+ double crossX = jetUnitVec.Y ()*lambdaPz - jetUnitVec.Z ()*lambdaPy;
154+ double crossY = jetUnitVec.Z ()*lambdaPx - jetUnitVec.X ()*lambdaPz;
155+ double crossZ = jetUnitVec.X ()*lambdaPy - jetUnitVec.Y ()*lambdaPx;
156+ double crossProductNorm = std::sqrt (crossX*crossX + crossY*crossY + crossZ*crossZ);
157+
158+ double ringObservable = 3 ./(lambdaWeakDecayConstant) * ((protonLikeStarUnitVec.X ()*crossX
159+ + protonLikeStarUnitVec.Y ()*crossY + protonLikeStarUnitVec.Z ()*cross_z)/crossProductNorm);
160+
161+ // Calculating error bars:
162+ double ringObservableSquared = ringObservable*ringObservable;
163+
164+ // Angular variables:
165+ double deltaPhiJet = v0phi - leadingJetPhi;
166+ double deltaThetaJet = ; // 3D angular separation
167+
168+ // Fill ring histograms: (1D, lambda 2D correlations and jet 2D correlations): (TODO)
169+ histos.fill (HIST (" Ring/hRingObservableDeltaPhi" ), 0 );
170+ histos.fill (HIST (" Ring/hRingObservableIntegrated" ), 0 );
171+
172+ histos.fill (HIST (" Ring/hRingObservableDeltaPhi" ), 0 );
173+ histos.fill (HIST (" Ring/hRingObservableIntegrated" ), 0 );
174+
175+
176+ // Extra kinematic criteria for Lambda candidates (removes polarization background):
177+ const bool kinematicLambdaCheck = (v0pt > 0.5 && v0pt < 1.5 ) && std::abs (lambdaRapidity) < 0.5 ;
178+ if (kinematicLambdaCheck){
179+ histos.fill (HIST (" RingKinematicCuts/hRingObservableDeltaPhi" ), 0 );
180+ histos.fill (HIST (" RingKinematicCuts/hRingObservableIntegrated" ), 0 );
181+ }
182+
183+
184+ // Extra selection criteria on jet candidates:
185+ const bool kinematicJetCheck = std::abs (leadingJetEta) < 0.5 ;
186+ if (kinematicJetCheck){ // This is redundant for jets with R=0.4, but for jets with R<0.4 the leading jet may be farther in eta.
187+
188+ }
189+
190+
191+ // Extra selection criteria on Lambda and jet candidates:
192+ if (kinematicLambdaCheck && kinematicJetCheck){
193+
194+ }
195+
196+
197+ } // end v0s loop
198+ } // end collisions
199+ }
200+ };
0 commit comments