Skip to content

Commit 4d7837f

Browse files
PushingMyRocheLimitsalibuildrolavick
authored
[PWGUD] Created Task for exclusive JPsi studies at Midrapidity (#14092)
Co-authored-by: ALICE Action Bot <alibuild@cern.ch> Co-authored-by: rolavick <roman.lavicka@cern.ch>
1 parent 4b409a0 commit 4d7837f

File tree

2 files changed

+337
-0
lines changed

2 files changed

+337
-0
lines changed

PWGUD/Tasks/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,3 +263,8 @@ o2physics_add_dpl_workflow(upc-test-rct-tables
263263
SOURCES upcTestRctTables.cxx
264264
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore
265265
COMPONENT_NAME Analysis)
266+
267+
o2physics_add_dpl_workflow(sg-exclusive-jpsi-midrapidity
268+
SOURCES sgExclusiveJpsiMidrapidity.cxx
269+
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore
270+
COMPONENT_NAME Analysis)
Lines changed: 332 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,332 @@
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 to study two pions candidates using SG derive data
13+
/// \author Levi Van Ryder (based on Anisa Khatun's UD Tutorial 5 example)
14+
/// \file sgExclusiveJpsiMidrapidity.cxx
15+
16+
#include "PWGUD/Core/SGSelector.h"
17+
#include "PWGUD/Core/SGTrackSelector.h"
18+
#include "PWGUD/DataModel/UDTables.h"
19+
20+
#include "Framework/AnalysisDataModel.h"
21+
#include "Framework/AnalysisTask.h"
22+
#include "Framework/runDataProcessing.h"
23+
24+
#include "Math/Vector4D.h"
25+
#include "TMath.h"
26+
27+
#include <cmath>
28+
#include <cstdlib>
29+
#include <string>
30+
#include <vector>
31+
32+
using namespace o2;
33+
using namespace o2::aod;
34+
using namespace o2::framework;
35+
using namespace o2::framework::expressions;
36+
using LorentzVector = ROOT::Math::PxPyPzMVector;
37+
38+
// Struct to define the analysis task
39+
struct SgExclusiveJpsiMidrapidity {
40+
// SGSelector object to manage track and collision selections
41+
SGSelector sgSelector;
42+
43+
// Number of Selection cuts
44+
static constexpr int numSelectionCuts = 16;
45+
46+
// Gapside rejection
47+
static constexpr int gapSideLow = 0;
48+
static constexpr int gapSideHigh = 2;
49+
50+
// Numbers for selections
51+
static constexpr int two = 2;
52+
53+
Configurable<float> fv0Cut{"fv0Cut", 100., "fv0aThreshold"};
54+
Configurable<float> ft0aCut{"ft0aCut", 100., "ft0aThreshold"};
55+
Configurable<float> ft0cCut{"ft0cCut", 50., "ft0cThreshold"};
56+
Configurable<float> fddaCut{"fddaCut", 10000., "fddaThreshold"};
57+
Configurable<float> fddcCut{"fddcCut", 10000., "fddcThreshold"};
58+
Configurable<float> zdcCut{"zdcCut", 10., "zdcThreshold"};
59+
Configurable<float> selectedGapSide{"selectedGapSide", 2, "gapSelection"};
60+
61+
// Track Selections
62+
Configurable<float> pvCut{"pvCut", 1.0, "Use Only PV tracks"};
63+
Configurable<float> dcazCut{"dcazCut", 2.0, "dcaZ cut"};
64+
Configurable<float> dcaxyCut{"dcaxyCut", 0.0, "dcaXY cut (0 for Pt-function)"};
65+
Configurable<float> tpcChi2Cut{"tpcChi2Cut", 4, "Max tpcChi2NCl"};
66+
Configurable<float> tpcNClsFindableCut{"tpcNClsFindableCut", 70, "Min tpcNClsFindable"};
67+
Configurable<float> itsChi2Cut{"itsChi2Cut", 36, "Max itsChi2NCl"};
68+
Configurable<float> etaCut{"etaCut", 0.9, "Track Pseudorapidity"};
69+
Configurable<float> ptCut{"ptCut", 0.01, "Track Pt"};
70+
Configurable<float> tpcCluster{"tpcCluster", 50, "No.of TPC cluster"};
71+
72+
// Kinematic cuts
73+
Configurable<float> pidCut{"pidCut", 5, "TPC PID"};
74+
Configurable<float> rapCut{"rapCut", 0.9, "Track rapidity"};
75+
Configurable<float> massMax{"massMax", 10, "Invariant Mass range high"};
76+
Configurable<float> massMin{"massMin", 0, "Invariant Mass range low"};
77+
Configurable<float> ptCoherent{"ptCoherent", 0.15, "Coherent selection"};
78+
79+
// defining histograms using histogram registry
80+
HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject};
81+
82+
//-----------------------------------------------------------------------------------------------------------------------
83+
void init(o2::framework::InitContext&)
84+
{
85+
86+
registry.add("GapSide", "Gap Side; Entries", kTH1F, {{4, -1.5, 2.5}});
87+
registry.add("TrueGapSide", "Gap Side; Entries", kTH1F, {{4, -1.5, 2.5}});
88+
89+
// Fill counter to see effect of each selection criteria
90+
auto hSelectionCounter = registry.add<TH1>("hSelectionCounter", "hSelectionCounter;;NEvents", HistType::kTH1I, {{20, 0., 20.}});
91+
92+
TString selectionCuts[numSelectionCuts] = {"NoSelection", "gapside", "goodtracks", "truegap", "2collcontrib", "2goodtrk", "TPCPID", "rapCut", "unlikesign", "mass_cut", "coherent", "incoherent", "likesign", "mass_cut", "coherent", "incoherent"};
93+
94+
for (int i = 0; i < numSelectionCuts; i++) {
95+
hSelectionCounter->GetXaxis()->SetBinLabel(i + 1, selectionCuts[i].Data());
96+
}
97+
// tracks
98+
registry.add("hTracks", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}});
99+
registry.add("hTracksPions", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}});
100+
registry.add("TwoPion/h2TracksPions", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}});
101+
102+
registry.add("hdEdx", "p vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {100, 0.0, 200.0}});
103+
registry.add("hdEdxPion", "p_{#pi} vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {100, 0.0, 200.0}});
104+
105+
registry.add("TwoPion/hNsigPi1vsPi2", "NSigmaPi(t1) vs NSigmapi (t2);n#sigma_{1};n#sigma_{2}", kTH2F, {{100, -15., 15.}, {100, -15., 15}});
106+
registry.add("TwoPion/hNsigEl1vsEl2", "NSigmaEl(t1) vs NSigmaEl (t2);n#sigma_{1};n#sigma_{2}", kTH2F, {{100, -15., 15.}, {100, -15., 15}});
107+
registry.add("TwoPion/hNsigPivsPt1", "Pt vs NSigmaPi (t1);#it{p_{t}}, GeV/c;n#sigma_{#pi}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}});
108+
registry.add("TwoPion/hNsigPivsPt2", "Pt vs NSigmaPi (t2);#it{p_{t}}, GeV/c;n#sigma_{#pi}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}});
109+
registry.add("TwoPion/hNsigElvsPt1", "Pt vs NSigmaEl (t1);#it{p_{t}}, GeV/c;n#sigma_{#e}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}});
110+
registry.add("TwoPion/hNsigElvsPt2", "Pt vs NSigmaEl (t2);#it{p_{t}}, GeV/c;n#sigma_{#e}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}});
111+
registry.add("TwoPion/hNsigMuvsPt1", "Pt vs NSigmaMu (t1);#it{p_{t}}, GeV/c;n#sigma_{#pi}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}});
112+
registry.add("TwoPion/hNsigMuvsPt2", "Pt vs NSigmaMu (t2);#it{p_{t}}, GeV/c;n#sigma_{#pi}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}});
113+
114+
registry.add("TwoPion/hPtsingle_track1", "Pt t1;#it{p_{t}}, GeV/c;", kTH1F, {{600, 0., 3.}});
115+
registry.add("TwoPion/hPtsingle_track2", "Pt t2;#it{p_{t}}, GeV/c;", kTH1F, {{600, 0., 3.}});
116+
registry.add("TwoPion/hEta_t1", "Eta of t1;#it{#eta};", kTH1F, {{100, -5., 5.}});
117+
registry.add("TwoPion/hEta_t2", "Eta of t2;#it{#eta};", kTH1F, {{100, -5., 5.}});
118+
registry.add("TwoPion/hP1", "P vs TPC signal;#it{P_{track}}, GeV/c; signal_{TPC} t1", kTH2F, {{100, 0., 2.}, {300, 0, 150}});
119+
registry.add("TwoPion/hTPCsig", "TPC signal;signal_{TPC} t2; signal_{TPC} t2", kTH2F, {{300, 0., 150.}, {300, 0, 150}});
120+
registry.add("TwoPion/hP2", "P vs TPC signal;#it{P_{track}}, GeV/c; signal_{TPC} t1", kTH2F, {{100, 0., 2.}, {300, 0, 150}});
121+
registry.add("TwoPion/hTPCsig1", "TPC signal;signal_{TPC} t2; signal_{TPC} t2", kTH2F, {{300, 0, 150.}, {300, 0, 150}});
122+
123+
registry.add("TwoPion/hMassLike", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}});
124+
registry.add("TwoPion/hMassUnlike", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}});
125+
registry.add("TwoPion/Coherent/hMassUnlikeCoherent", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}});
126+
registry.add("TwoPion/Coherent/hMassLikeCoherent", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}});
127+
registry.add("TwoPion/Incoherent/hMassUnlikeInCoherent", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}});
128+
registry.add("TwoPion/Incoherent/hMassLikeInCoherent", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}});
129+
130+
registry.add("TwoPion/hPt", "Pt;#it{p_{t}}, GeV/c;", kTH1D, {{1000, 0., 10.}});
131+
registry.add("TwoPion/hPtLike", "Pt;#it{p_{t}}, GeV/c;", kTH1D, {{1000, 0., 10.}});
132+
registry.add("TwoPion/hEta", "Eta;#it{#eta};", kTH1F, {{500, -10., 10.}});
133+
registry.add("TwoPion/hRap", "Rapidity;#it{y};", kTH1F, {{500, -10., 10.}});
134+
registry.add("TwoPion/hPhiSystem", "Phi;#it{#Phi};", kTH1F, {{250, 0., o2::constants::math::TwoPI}});
135+
registry.add("TwoPion/hMPt", "Inv.M vs Pt;M, GeV/c^{2};#it{P_{t}}, GeV/c;", kTH2F, {{100, 0., 10.}, {100, 0., 10.}});
136+
}
137+
138+
using UDTracksFull = soa::Join<aod::UDTracks, aod::UDTracksPID, aod::UDTracksExtra, aod::UDTracksFlags, aod::UDTracksDCA>;
139+
140+
using UDCollisionsFull = soa::Join<aod::UDCollisions, aod::SGCollisions, aod::UDCollisionsSels, aod::UDZdcsReduced>;
141+
142+
//__________________________________________________________________________
143+
// Main process
144+
void process(UDCollisionsFull::iterator const& collision, UDTracksFull const& tracks)
145+
{
146+
// No selection criteria
147+
registry.fill(HIST("hSelectionCounter"), 0);
148+
149+
// Accessing gap sides
150+
int gapSide = collision.gapSide();
151+
if (gapSide < gapSideLow || gapSide > gapSideHigh)
152+
return;
153+
154+
registry.fill(HIST("hSelectionCounter"), 1);
155+
156+
// Accessing FIT information for further exclusivity and/or inclusivity
157+
int truegapSide = sgSelector.trueGap(collision, fv0Cut, ft0aCut, ft0cCut, zdcCut);
158+
159+
// Initiating track parameters to select good tracks, values to be optimized in the configurables, parameters will be taken from SGtrackselector.h task included in the header
160+
std::vector<float> parameters = {pvCut, dcazCut, dcaxyCut, tpcChi2Cut, tpcNClsFindableCut, itsChi2Cut, etaCut, ptCut};
161+
162+
registry.fill(HIST("GapSide"), gapSide);
163+
registry.fill(HIST("TrueGapSide"), truegapSide);
164+
165+
// Gap side to be selected in the configurables
166+
gapSide = truegapSide;
167+
168+
if (gapSide == selectedGapSide) {
169+
170+
registry.fill(HIST("hSelectionCounter"), 2);
171+
172+
if (collision.flags() != 1)
173+
return; // UPC setting vs std setting
174+
//____________________________________________________________________________________
175+
176+
// Create LorentzVector to store all tracks, Pion tracks and TPC Pion PID
177+
std::vector<LorentzVector> onlyPionTracks;
178+
std::vector<float> onlyPionSigma;
179+
std::vector<decltype(tracks.begin())> rawPionTracks;
180+
181+
// initialize pair 4-vector to zero before accumulation
182+
LorentzVector p(0.0, 0.0, 0.0, 0.0);
183+
184+
registry.fill(HIST("hTracks"), tracks.size());
185+
186+
for (const auto& t : tracks) {
187+
// Apply good track selection criteria
188+
if (!trackselector(t, parameters))
189+
continue;
190+
191+
double dEdx = t.tpcSignal();
192+
193+
registry.fill(HIST("hdEdx"), t.tpcInnerParam() / t.sign(), dEdx);
194+
195+
// Create Lorentz vector for this track (use constructor, portable)
196+
LorentzVector a(t.px(), t.py(), t.pz(), o2::constants::physics::MassPionCharged);
197+
198+
// Apply TPC pion sigma
199+
auto nSigmaPi = t.tpcNSigmaPi();
200+
if (std::fabs(nSigmaPi) < pidCut) {
201+
onlyPionTracks.push_back(a);
202+
onlyPionSigma.push_back(nSigmaPi);
203+
rawPionTracks.push_back(t);
204+
registry.fill(HIST("hdEdxPion"), t.tpcInnerParam() / t.sign(), dEdx);
205+
}
206+
}
207+
208+
registry.fill(HIST("hTracksPions"), onlyPionTracks.size());
209+
210+
//_____________________________________
211+
// Add all onlyPionTracks into p
212+
for (const auto& pion : onlyPionTracks) {
213+
p += pion;
214+
}
215+
216+
//_____________________________________
217+
// Selecting collisions with Two PV contributors
218+
if (collision.numContrib() == two) {
219+
220+
registry.fill(HIST("hSelectionCounter"), 3);
221+
222+
// Selecting only Two good tracks
223+
if ((static_cast<int>(rawPionTracks.size()) == two) && (static_cast<int>(onlyPionTracks.size()) == two)) {
224+
225+
registry.fill(HIST("hSelectionCounter"), 4);
226+
227+
registry.fill(HIST("TwoPion/h2TracksPions"), onlyPionTracks.size());
228+
229+
registry.fill(HIST("TwoPion/hNsigPivsPt1"), onlyPionTracks[0].Pt(), rawPionTracks[0].tpcNSigmaPi());
230+
registry.fill(HIST("TwoPion/hNsigPivsPt2"), onlyPionTracks[1].Pt(), rawPionTracks[1].tpcNSigmaPi());
231+
registry.fill(HIST("TwoPion/hTPCsig"), rawPionTracks[0].tpcSignal(), rawPionTracks[1].tpcSignal());
232+
registry.fill(HIST("TwoPion/hNsigPi1vsPi2"), rawPionTracks[0].tpcNSigmaPi(), rawPionTracks[1].tpcNSigmaPi());
233+
234+
// Make sure two good tracks are within TPC pion sigma limit
235+
if ((onlyPionSigma[0] * onlyPionSigma[0] + onlyPionSigma[1] * onlyPionSigma[1]) > (pidCut * pidCut)) {
236+
return;
237+
}
238+
239+
registry.fill(HIST("hSelectionCounter"), 5);
240+
241+
// Rapidity of midrapidity acceptance
242+
if ((p.Rapidity() < -rapCut) || (p.Rapidity() > rapCut)) {
243+
return;
244+
}
245+
246+
registry.fill(HIST("hSelectionCounter"), 6);
247+
248+
// opposite sign tracks
249+
if (rawPionTracks[0].sign() != rawPionTracks[1].sign()) {
250+
251+
registry.fill(HIST("hSelectionCounter"), 7);
252+
registry.fill(HIST("TwoPion/hMassUnlike"), p.M());
253+
254+
// Flexible mass limits, can be selected in the configurable
255+
if ((p.M() > massMin) && (p.M() < massMax)) {
256+
257+
registry.fill(HIST("hSelectionCounter"), 8);
258+
259+
registry.fill(HIST("TwoPion/hPt"), p.Pt());
260+
registry.fill(HIST("TwoPion/hEta"), p.Eta());
261+
registry.fill(HIST("TwoPion/hRap"), p.Rapidity());
262+
registry.fill(HIST("TwoPion/hPhiSystem"), p.Phi());
263+
registry.fill(HIST("TwoPion/hMPt"), p.M(), p.Pt());
264+
265+
// flexible pt limit for selecting coherent Rho(0)
266+
if (p.Pt() < ptCoherent) {
267+
268+
registry.fill(HIST("hSelectionCounter"), 9);
269+
270+
// Quality Control plots after coherent Rho(0) selection
271+
registry.fill(HIST("TwoPion/hEta_t1"), onlyPionTracks[0].Eta());
272+
registry.fill(HIST("TwoPion/hEta_t2"), onlyPionTracks[1].Eta());
273+
registry.fill(HIST("TwoPion/hPtsingle_track1"), onlyPionTracks[0].Pt());
274+
registry.fill(HIST("TwoPion/hPtsingle_track2"), onlyPionTracks[1].Pt());
275+
276+
registry.fill(HIST("TwoPion/hNsigMuvsPt1"), onlyPionTracks[0].Pt(), rawPionTracks[0].tpcNSigmaPi());
277+
registry.fill(HIST("TwoPion/hNsigMuvsPt2"), onlyPionTracks[1].Pt(), rawPionTracks[1].tpcNSigmaPi());
278+
registry.fill(HIST("TwoPion/hNsigElvsPt1"), onlyPionTracks[0].Pt(), rawPionTracks[0].tpcNSigmaEl());
279+
registry.fill(HIST("TwoPion/hNsigElvsPt2"), onlyPionTracks[1].Pt(), rawPionTracks[1].tpcNSigmaEl());
280+
registry.fill(HIST("TwoPion/hNsigEl1vsEl2"), rawPionTracks[0].tpcNSigmaPi(), rawPionTracks[1].tpcNSigmaPi());
281+
282+
registry.fill(HIST("TwoPion/hP1"), onlyPionTracks[0].P(), rawPionTracks[0].tpcSignal());
283+
registry.fill(HIST("TwoPion/hP2"), onlyPionTracks[1].P(), rawPionTracks[1].tpcSignal());
284+
registry.fill(HIST("TwoPion/hTPCsig1"), rawPionTracks[0].tpcSignal(), rawPionTracks[1].tpcSignal());
285+
286+
registry.fill(HIST("TwoPion/Coherent/hMassUnlikeCoherent"), p.M());
287+
}
288+
// Incoherent Rho(0) selection
289+
if (p.Pt() > ptCoherent) {
290+
registry.fill(HIST("hSelectionCounter"), 10);
291+
registry.fill(HIST("TwoPion/Incoherent/hMassUnlikeInCoherent"), p.M());
292+
}
293+
}
294+
}
295+
296+
// Same charge particles
297+
if (rawPionTracks[0].sign() == rawPionTracks[1].sign()) {
298+
299+
registry.fill(HIST("hSelectionCounter"), 11);
300+
registry.fill(HIST("TwoPion/hMassLike"), p.M());
301+
302+
// Mass limit
303+
if ((p.M() > massMin) && (p.M() < massMax)) {
304+
305+
registry.fill(HIST("hSelectionCounter"), 12);
306+
registry.fill(HIST("TwoPion/hPtLike"), p.Pt());
307+
308+
// Coherent Rho(0) selection
309+
if (p.Pt() < ptCoherent) {
310+
311+
registry.fill(HIST("hSelectionCounter"), 13);
312+
registry.fill(HIST("TwoPion/Coherent/hMassLikeCoherent"), p.M());
313+
}
314+
// Incoherent Rho(0) selection
315+
if (p.Pt() > ptCoherent) {
316+
317+
registry.fill(HIST("hSelectionCounter"), 14);
318+
registry.fill(HIST("TwoPion/Incoherent/hMassLikeInCoherent"), p.M());
319+
}
320+
}
321+
}
322+
}
323+
}
324+
}
325+
}
326+
};
327+
328+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
329+
{
330+
return WorkflowSpec{
331+
adaptAnalysisTask<SgExclusiveJpsiMidrapidity>(cfgc)};
332+
}

0 commit comments

Comments
 (0)