Skip to content

Commit dc96661

Browse files
authored
[PWGUD] PWG-UD: Test on rho' in UPCs using UD tables (#9747)
1 parent f852924 commit dc96661

File tree

2 files changed

+290
-0
lines changed

2 files changed

+290
-0
lines changed

PWGUD/Tasks/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,11 @@ o2physics_add_dpl_workflow(upc-rho-analysis
208208
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector
209209
COMPONENT_NAME Analysis)
210210

211+
o2physics_add_dpl_workflow(upc-rho-prime-analysis
212+
SOURCES upcRhoPrimeAnalysis.cxx
213+
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector
214+
COMPONENT_NAME Analysis)
215+
211216
o2physics_add_dpl_workflow(event-by-event
212217
SOURCES eventByevent.cxx
213218
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector
Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
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+
/// \brief Task for analysis of rho' in UPCs using UD tables (from SG producer).
13+
/// \author Cesar Ramirez, cesar.ramirez@cern.ch
14+
15+
#include <string> // Para std::string
16+
#include <vector> // Para std::vector
17+
18+
#include "Framework/AnalysisTask.h"
19+
#include "Framework/AnalysisDataModel.h"
20+
#include "Framework/runDataProcessing.h"
21+
22+
#include "Math/Vector4D.h" // similiar to TLorentzVector (which is now legacy apparently)
23+
#include "random"
24+
25+
#include "Common/DataModel/PIDResponse.h"
26+
27+
#include "PWGUD/DataModel/UDTables.h"
28+
#include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h"
29+
30+
using namespace o2;
31+
using namespace o2::framework;
32+
using namespace o2::framework::expressions;
33+
34+
using FullUDSgCollision = soa::Join<aod::UDCollisions, aod::UDCollisionsSels, aod::UDZdcsReduced, aod::SGCollisions>::iterator;
35+
using FullUDTracks = soa::Join<aod::UDTracks, aod::UDTracksExtra, aod::UDTracksDCA, aod::UDTracksPID, aod::UDTracksFlags>;
36+
37+
namespace o2::aod
38+
{
39+
namespace fourpi
40+
{
41+
42+
// for event
43+
DECLARE_SOA_COLUMN(RunNumber, runNumber, int32_t);
44+
45+
// for Rhos
46+
DECLARE_SOA_COLUMN(M, m, double);
47+
DECLARE_SOA_COLUMN(Pt, pt, double);
48+
DECLARE_SOA_COLUMN(Eta, eta, double);
49+
DECLARE_SOA_COLUMN(Phi, phi, double);
50+
51+
// for vertex
52+
DECLARE_SOA_COLUMN(PosX, posX, double);
53+
DECLARE_SOA_COLUMN(PosY, posY, double);
54+
DECLARE_SOA_COLUMN(PosZ, posZ, double);
55+
56+
// for other
57+
DECLARE_SOA_COLUMN(TotalCharge, totalCharge, int);
58+
59+
// info Detec
60+
DECLARE_SOA_COLUMN(TotalFT0AmplitudeA, totalFT0AmplitudeA, float);
61+
DECLARE_SOA_COLUMN(TotalFT0AmplitudeC, totalFT0AmplitudeC, float);
62+
DECLARE_SOA_COLUMN(TotalFV0AmplitudeA, totalFV0AmplitudeA, float);
63+
DECLARE_SOA_COLUMN(TotalFDDAmplitudeA, totalFDDAmplitudeA, float);
64+
DECLARE_SOA_COLUMN(TotalFDDAmplitudeC, totalFDDAmplitudeC, float);
65+
DECLARE_SOA_COLUMN(TimeFT0A, timeFT0A, float);
66+
DECLARE_SOA_COLUMN(TimeFT0C, timeFT0C, float);
67+
DECLARE_SOA_COLUMN(TimeFV0A, timeFV0A, float);
68+
DECLARE_SOA_COLUMN(TimeFDDA, timeFDDA, float);
69+
DECLARE_SOA_COLUMN(TimeFDDC, timeFDDC, float);
70+
71+
// for pion tracks
72+
// DECLARE_SOA_COLUMN(TrackSign, trackSign, std::vector<int>);
73+
// DECLARE_SOA_COLUMN(TrackM, trackM, std::vector<double>);
74+
// DECLARE_SOA_COLUMN(TrackPt, trackPt, std::vector<double>);
75+
// DECLARE_SOA_COLUMN(TrackEta, trackEta, std::vector<double>);
76+
// DECLARE_SOA_COLUMN(TrackPhi, trackPhi, std::vector<double>);
77+
78+
} // namespace fourpi
79+
DECLARE_SOA_TABLE(SYSTEMTREE, "AOD", "SystemTree", fourpi::RunNumber, fourpi::M, fourpi::Pt, fourpi::Eta, fourpi::Phi,
80+
fourpi::PosX, fourpi::PosY, fourpi::PosZ, fourpi::TotalCharge, fourpi::TotalFT0AmplitudeA, fourpi::TotalFT0AmplitudeC, fourpi::TotalFV0AmplitudeA,
81+
fourpi::TotalFDDAmplitudeA, fourpi::TotalFDDAmplitudeC, fourpi::TimeFT0A, fourpi::TimeFT0C, fourpi::TimeFV0A, fourpi::TimeFDDA, fourpi::TimeFDDC);
82+
} // namespace o2::aod
83+
84+
struct upcRhoPrimeAnalysis {
85+
Produces<aod::SYSTEMTREE> systemTree;
86+
87+
double PcEtaCut = 0.9; // physics coordination recommendation
88+
89+
Configurable<bool> specifyGapSide{"specifyGapSide", true, "specify gap side for SG/DG produced data"};
90+
Configurable<int> gapSide{"gapSide", 2, "gap side for SG produced data"};
91+
Configurable<bool> requireTof{"requireTof", false, "require TOF signal"};
92+
93+
Configurable<double> collisionsPosZMaxCut{"collisionsPosZMaxCut", 10.0, "max Z position cut on collisions"};
94+
Configurable<double> ZNcommonEnergyCut{"ZNcommonEnergyCut", 0.0, "ZN common energy cut"};
95+
Configurable<double> ZNtimeCut{"ZNtimeCut", 2.0, "ZN time cut"};
96+
97+
Configurable<double> tracksTpcNSigmaPiCut{"tracksTpcNSigmaPiCut", 3.0, "TPC nSigma pion cut"};
98+
Configurable<double> tracksDcaMaxCut{"tracksDcaMaxCut", 1.0, "max DCA cut on tracks"};
99+
100+
Configurable<double> systemMassMinCut{"systemMassMinCut", 0.5, "min M cut for reco system"};
101+
Configurable<double> systemMassMaxCut{"systemMassMaxCut", 1.2, "max M cut for reco system"};
102+
Configurable<double> systemPtCut{"systemPtMaxCut", 0.1, "max pT cut for reco system"};
103+
Configurable<double> systemYCut{"systemYCut", 0.9, "rapiditiy cut for reco system"};
104+
105+
ConfigurableAxis mAxis{"mAxis", {1000, 0.0, 10.0}, "m (GeV/#it{c}^{2})"};
106+
ConfigurableAxis mCutAxis{"mCutAxis", {70, 0.5, 1.2}, "m (GeV/#it{c}^{2})"};
107+
ConfigurableAxis ptAxis{"ptAxis", {1000, 0.0, 10.0}, "p_{T} (GeV/#it{c})"};
108+
ConfigurableAxis ptCutAxis{"ptCutAxis", {300, 0.0, 0.3}, "p_{T} (GeV/#it{c})"};
109+
ConfigurableAxis pt2Axis{"pt2Axis", {300, 0.0, 0.09}, "p_{T}^{2} (GeV^{2}/#it{c}^{2})"};
110+
ConfigurableAxis etaAxis{"etaAxis", {180, -0.9, 0.9}, "#eta"};
111+
ConfigurableAxis yAxis{"yAxis", {180, -0.9, 0.9}, "y"};
112+
ConfigurableAxis phiAxis{"phiAxis", {180, 0.0, o2::constants::math::TwoPI}, "#phi"};
113+
ConfigurableAxis phiAsymmAxis{"phiAsymmAxis", {182, -o2::constants::math::PI, o2::constants::math::PI}, "#phi"};
114+
ConfigurableAxis momentumFromPhiAxis{"momentumFromPhiAxis", {400, -0.1, 0.1}, "p (GeV/#it{c})"};
115+
ConfigurableAxis ptQuantileAxis{"ptQuantileAxis", {0, 0.0181689, 0.0263408, 0.0330488, 0.0390369, 0.045058, 0.0512604, 0.0582598, 0.066986, 0.0788085, 0.1}, "p_{T} (GeV/#it{c})"};
116+
117+
HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject};
118+
119+
void init(o2::framework::InitContext&)
120+
{
121+
// selection counter
122+
std::vector<std::string> selectionCounterLabels = {"all tracks", "PV contributor", "ITS + TPC hit", "TOF requirement", "DCA cut", "#eta cut", "2D TPC n#sigma_{#pi} cut"};
123+
124+
// 4PI SYSTEM
125+
// registry.add("4pi/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mAxis});
126+
// registry.add("4pi/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptAxis});
127+
// registry.add("4pi/hEta", ";Eta (1);counts", kTH1D, {etaAxis});
128+
// registry.add("4pi/hPhi", ";Phi ();counts", kTH1D, {phiAxis});
129+
}
130+
131+
template <typename C>
132+
bool collisionPassesCuts(const C& collision) // collision cuts
133+
{
134+
if (std::abs(collision.posZ()) > collisionsPosZMaxCut)
135+
return false;
136+
if (specifyGapSide && collision.gapSide() != gapSide)
137+
return false;
138+
return true;
139+
}
140+
141+
template <typename T>
142+
bool trackPassesCuts(const T& track) // track cuts (PID done separately)
143+
{
144+
if (!track.isPVContributor())
145+
return false;
146+
if (!track.hasITS() || !track.hasTPC())
147+
return false;
148+
if (requireTof && !track.hasTOF())
149+
return false;
150+
if (std::abs(track.dcaZ()) > tracksDcaMaxCut || std::abs(track.dcaXY()) > (0.0182 + 0.0350 / std::pow(track.pt(), 1.01))) // Run 2 dynamic DCA cut
151+
return false;
152+
if (std::abs(eta(track.px(), track.py(), track.pz())) > PcEtaCut)
153+
return false;
154+
return true;
155+
}
156+
157+
template <typename T>
158+
bool tracksPassPiPID(const T& cutTracks) // n-dimensional PID cut
159+
{
160+
double radius = 0.0;
161+
for (const auto& track : cutTracks)
162+
radius += std::pow(track.tpcNSigmaPi(), 2);
163+
return radius < std::pow(tracksTpcNSigmaPiCut, 2);
164+
}
165+
166+
template <typename T>
167+
double tracksTotalCharge(const T& cutTracks) // total charge of selected tracks
168+
{
169+
double charge = 0.0;
170+
for (const auto& track : cutTracks)
171+
charge += track.sign();
172+
return charge;
173+
}
174+
175+
bool systemPassCuts(const ROOT::Math::PxPyPzMVector& system) // system cuts
176+
{
177+
if (system.M() < systemMassMinCut || system.M() > systemMassMaxCut)
178+
return false;
179+
if (system.Pt() > systemPtCut)
180+
return false;
181+
if (std::abs(system.Rapidity()) > systemYCut)
182+
return false;
183+
return true;
184+
}
185+
186+
ROOT::Math::PxPyPzMVector reconstructSystem(const std::vector<ROOT::Math::PxPyPzMVector>& cutTracks4Vecs) // reconstruct system from 4-vectors
187+
{
188+
ROOT::Math::PxPyPzMVector system;
189+
for (const auto& track4Vec : cutTracks4Vecs)
190+
system += track4Vec;
191+
return system;
192+
}
193+
194+
double deltaPhi(const ROOT::Math::PxPyPzMVector& p1, const ROOT::Math::PxPyPzMVector& p2)
195+
{
196+
double dPhi = p1.Phi() - p2.Phi();
197+
if (dPhi > o2::constants::math::PI)
198+
dPhi -= o2::constants::math::TwoPI;
199+
else if (dPhi < -o2::constants::math::PI)
200+
dPhi += o2::constants::math::TwoPI;
201+
return dPhi; // calculate delta phi in (-pi, pi)
202+
}
203+
204+
double getPhiRandom(const std::vector<ROOT::Math::PxPyPzMVector>& cutTracks4Vecs) // decay phi anisotropy
205+
{ // two possible definitions of phi: randomize the tracks
206+
std::vector<int> indices = {0, 1};
207+
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); // get time-based seed
208+
std::shuffle(indices.begin(), indices.end(), std::default_random_engine(seed)); // shuffle indices
209+
// calculate phi
210+
ROOT::Math::PxPyPzMVector pOne = cutTracks4Vecs[indices[0]];
211+
ROOT::Math::PxPyPzMVector pTwo = cutTracks4Vecs[indices[1]];
212+
ROOT::Math::PxPyPzMVector pPlus = pOne + pTwo;
213+
ROOT::Math::PxPyPzMVector pMinus = pOne - pTwo;
214+
return deltaPhi(pPlus, pMinus);
215+
}
216+
217+
template <typename T>
218+
double getPhiCharge(const T& cutTracks, const std::vector<ROOT::Math::PxPyPzMVector>& cutTracks4Vecs)
219+
{ // two possible definitions of phi: charge-based assignment
220+
ROOT::Math::PxPyPzMVector pOne, pTwo;
221+
if (cutTracks[0].sign() > 0) {
222+
pOne = cutTracks4Vecs[0];
223+
pTwo = cutTracks4Vecs[1];
224+
} else {
225+
pOne = cutTracks4Vecs[1];
226+
pTwo = cutTracks4Vecs[0];
227+
}
228+
ROOT::Math::PxPyPzMVector pPlus = pOne + pTwo;
229+
ROOT::Math::PxPyPzMVector pMinus = pOne - pTwo;
230+
return deltaPhi(pPlus, pMinus);
231+
}
232+
233+
void processReco(FullUDSgCollision const& collision, FullUDTracks const& tracks)
234+
{
235+
236+
if (!collisionPassesCuts(collision))
237+
return;
238+
239+
// vectors for storing selected tracks and their 4-vectors
240+
std::vector<decltype(tracks.begin())> cutTracks;
241+
std::vector<ROOT::Math::PxPyPzMVector> cutTracks4Vecs;
242+
243+
// int trackCounter = 0;
244+
for (const auto& track : tracks) {
245+
246+
if (!trackPassesCuts(track))
247+
continue;
248+
// trackCounter++;
249+
cutTracks.push_back(track);
250+
cutTracks4Vecs.push_back(ROOT::Math::PxPyPzMVector(track.px(), track.py(), track.pz(), o2::constants::physics::MassPionCharged)); // apriori assume pion mass
251+
}
252+
253+
if (!tracksPassPiPID(cutTracks))
254+
return;
255+
// reonstruct system and calculate total charge, save commonly used values into variables
256+
ROOT::Math::PxPyPzMVector system = reconstructSystem(cutTracks4Vecs);
257+
int totalCharge = tracksTotalCharge(cutTracks);
258+
int nTracks = cutTracks.size();
259+
double mass = system.M();
260+
double pT = system.Pt();
261+
// double pTsquare = pT * pT;
262+
double rapidity = system.Rapidity();
263+
double systemPhi = system.Phi() + o2::constants::math::PI;
264+
265+
if (nTracks == 4 && tracksTotalCharge(cutTracks) == 0) { // 4pi system
266+
267+
systemTree(collision.runNumber(), mass, pT, rapidity, systemPhi, collision.posX(), collision.posY(), collision.posZ(), totalCharge,
268+
collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.timeFV0A(), collision.totalFDDAmplitudeA(), collision.totalFDDAmplitudeC(),
269+
collision.timeFT0A(), collision.timeFT0C(), collision.timeFV0A(), collision.timeFDDA(), collision.timeFDDC());
270+
271+
// registry.fill(HIST("4pi/hM"), mass);
272+
// registry.fill(HIST("4pi/hPt"), pT);
273+
// registry.fill(HIST("4pi/hEta"), rapiditiy);
274+
// registry.fill(HIST("4pi/hPhi"), system);
275+
}
276+
// std::cout<<"Hello World"<<std::endl;
277+
}
278+
PROCESS_SWITCH(upcRhoPrimeAnalysis, processReco, "analyse reco tracks", true);
279+
};
280+
281+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
282+
{
283+
return WorkflowSpec{
284+
o2::framework::adaptAnalysisTask<upcRhoPrimeAnalysis>(cfgc)};
285+
}

0 commit comments

Comments
 (0)