Skip to content

Commit d6321eb

Browse files
cnkosteralibuild
andauthored
[PWGCF] Task for flow analysis relative to Spectator Plane (AliceO2Group#8739)
Co-authored-by: ALICE Action Bot <[email protected]>
1 parent 3cde666 commit d6321eb

File tree

2 files changed

+348
-0
lines changed

2 files changed

+348
-0
lines changed

PWGCF/Flow/Tasks/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,8 @@ o2physics_add_dpl_workflow(flow-pid-cme
5353
SOURCES pidcme.cxx
5454
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore
5555
COMPONENT_NAME Analysis)
56+
57+
o2physics_add_dpl_workflow(flow-sp
58+
SOURCES flowSP.cxx
59+
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore
60+
COMPONENT_NAME Analysis)

PWGCF/Flow/Tasks/flowSP.cxx

Lines changed: 343 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,343 @@
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+
// author: Noor Koster [email protected]
13+
14+
#include <CCDB/BasicCCDBManager.h>
15+
#include <DataFormatsParameters/GRPObject.h>
16+
#include <DataFormatsParameters/GRPMagField.h>
17+
#include <algorithm>
18+
#include <numeric>
19+
#include <vector>
20+
21+
#include "Framework/runDataProcessing.h"
22+
#include "Framework/AnalysisTask.h"
23+
#include "Framework/ASoAHelpers.h"
24+
#include "Framework/RunningWorkflowInfo.h"
25+
#include "Framework/HistogramRegistry.h"
26+
27+
#include "Common/DataModel/EventSelection.h"
28+
#include "Common/Core/TrackSelection.h"
29+
#include "Common/DataModel/TrackSelectionTables.h"
30+
#include "Common/DataModel/Multiplicity.h"
31+
#include "Common/DataModel/Centrality.h"
32+
#include "Common/DataModel/Qvectors.h"
33+
34+
#include "PWGCF/DataModel/SPTableZDC.h"
35+
#include "TF1.h"
36+
37+
using namespace o2;
38+
using namespace o2::framework;
39+
using namespace o2::framework::expressions;
40+
// using namespace o2::analysis;
41+
42+
#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable<TYPE> NAME{#NAME, DEFAULT, HELP};
43+
44+
struct flowAnalysisSP {
45+
46+
O2_DEFINE_CONFIGURABLE(cfgDCAxy, float, 0.2, "Cut on DCA in the transverse direction (cm)");
47+
O2_DEFINE_CONFIGURABLE(cfgDCAz, float, 2, "Cut on DCA in the longitudinal direction (cm)");
48+
O2_DEFINE_CONFIGURABLE(cfgNcls, float, 70, "Cut on number of TPC clusters found");
49+
O2_DEFINE_CONFIGURABLE(cfgPtmin, float, 0.2, "minimum pt (GeV/c)");
50+
O2_DEFINE_CONFIGURABLE(cfgPtmax, float, 10, "maximum pt (GeV/c)");
51+
O2_DEFINE_CONFIGURABLE(cfgEta, float, 0.8, "eta cut");
52+
O2_DEFINE_CONFIGURABLE(cfgVtxZ, float, 10, "vertex cut (cm)");
53+
O2_DEFINE_CONFIGURABLE(cfgMagField, float, 99999, "Configurable magnetic field; default CCDB will be queried");
54+
O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, true, "Bool to enable Additional Event Cut");
55+
O2_DEFINE_CONFIGURABLE(cfgUseAdditionalTrackCut, bool, true, "Bool to enable Additional Track Cut");
56+
57+
O2_DEFINE_CONFIGURABLE(cfgDoubleTrackFunction, bool, true, "Include track cut at low pt");
58+
O2_DEFINE_CONFIGURABLE(cfgTrackCutSize, float, 0.06, "Spread of track cut");
59+
O2_DEFINE_CONFIGURABLE(cfgMaxOccupancy, int, 500, "Maximum occupancy of selected events");
60+
O2_DEFINE_CONFIGURABLE(cfgNoSameBunchPileupCut, bool, true, "kNoSameBunchPileupCut");
61+
O2_DEFINE_CONFIGURABLE(cfgIsGoodZvtxFT0vsPV, bool, true, "kIsGoodZvtxFT0vsPV");
62+
O2_DEFINE_CONFIGURABLE(cfgNoCollInTimeRangeStandard, bool, true, "kNoCollInTimeRangeStandard");
63+
O2_DEFINE_CONFIGURABLE(cfgDoOccupancySel, bool, true, "Bool for event selection on detector occupancy");
64+
O2_DEFINE_CONFIGURABLE(cfgMultCut, bool, true, "Use additional evenr cut on mult correlations");
65+
O2_DEFINE_CONFIGURABLE(cfgTVXinTRD, bool, true, "Use kTVXinTRD (reject TRD triggered events)");
66+
O2_DEFINE_CONFIGURABLE(cfgIsVertexITSTPC, bool, true, "Selects collisions with at least one ITS-TPC track");
67+
68+
Filter collisionFilter = nabs(aod::collision::posZ) < cfgVtxZ;
69+
Filter trackFilter = nabs(aod::track::eta) < cfgEta && aod::track::pt > cfgPtmin&& aod::track::pt < cfgPtmax && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && nabs(aod::track::dcaXY) < cfgDCAxy&& nabs(aod::track::dcaZ) < cfgDCAz;
70+
using myCollisions = soa::Filtered<soa::Join<aod::Collisions, aod::EvSels, aod::Mults, aod::CentFT0Cs, aod::SPTableZDC, aod::Qvectors>>;
71+
using myTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TrackSelection, aod::TracksDCA>>;
72+
73+
// Connect to ccdb
74+
Service<ccdb::BasicCCDBManager> ccdb;
75+
76+
HistogramRegistry registry{"registry"};
77+
78+
// Event selection cuts - Alex
79+
TF1* fPhiCutLow = nullptr;
80+
TF1* fPhiCutHigh = nullptr;
81+
TF1* fMultPVCutLow = nullptr;
82+
TF1* fMultPVCutHigh = nullptr;
83+
TF1* fMultCutLow = nullptr;
84+
TF1* fMultCutHigh = nullptr;
85+
TF1* fMultMultPVCut = nullptr;
86+
87+
void init(InitContext const&)
88+
{
89+
std::vector<double> ptbinning = {0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.2, 2.4, 2.6, 2.8, 3, 3.5, 4, 5, 6, 8, 10};
90+
91+
AxisSpec phiModAxis = {100, 0, constants::math::PI / 9, "fmod(#varphi,#pi/9)"};
92+
AxisSpec ptAxis = {ptbinning, "#it{p}_{T} GeV/#it{c}"};
93+
94+
ccdb->setURL("http://alice-ccdb.cern.ch");
95+
ccdb->setCaching(true);
96+
ccdb->setLocalObjectValidityChecking();
97+
98+
int64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
99+
ccdb->setCreatedNotAfter(now);
100+
101+
registry.add<TH1>("hSPplaneA", "hSPplaneA", kTH1D, {{100, -3, 3}});
102+
registry.add<TH1>("hSPplaneC", "hSPplaneC", kTH1D, {{100, -3, 3}});
103+
registry.add<TH1>("hSPplaneA-C", "hSPplaneA-C", kTH1D, {{100, -3, 3}});
104+
registry.add<TH1>("hCent", "hCent", kTH1D, {{80, 0, 80}});
105+
106+
registry.add<TH1>("hqIm", "hqIm", kTH1D, {{100, -2, 2}});
107+
registry.add<TH1>("hqRe", "hqRe", kTH1D, {{100, -2, 2}});
108+
109+
registry.add<TProfile>("hCosdPhi", "hCosdPhi; Centrality(%); #LT Cos( #Psi^{A}-#Psi^{C})#GT", kTProfile, {{80, 0, 80}});
110+
registry.add<TProfile>("hSindPhi", "hSindPhi; Centrality(%); #LT Sin( #Psi^{A}-#Psi^{C})#GT", kTProfile, {{80, 0, 80}});
111+
registry.add<TProfile>("hSPlaneRes", "hSPlaneRes; Centrality(%); ", kTProfile, {{80, 0, 80}});
112+
113+
registry.add("pt_phi_bef", "", {HistType::kTH2D, {ptAxis, phiModAxis}});
114+
registry.add("pt_phi_aft", "", {HistType::kTH2D, {ptAxis, phiModAxis}});
115+
116+
registry.add<TProfile>("v1_eta", "", kTProfile, {{10, -.8, .8}});
117+
registry.add<TProfile>("v1A_eta", "", kTProfile, {{10, -.8, .8}});
118+
registry.add<TProfile>("v1C_eta", "", kTProfile, {{10, -.8, .8}});
119+
registry.add<TProfile>("v1AC_eta", "", kTProfile, {{10, -.8, .8}});
120+
121+
registry.add<TProfile>("v2_cent", "", kTProfile, {{80, 0, 80}});
122+
registry.add<TProfile>("v2A_cent", "", kTProfile, {{80, 0, 80}});
123+
registry.add<TProfile>("v2C_cent", "", kTProfile, {{80, 0, 80}});
124+
registry.add<TProfile>("v2AC_cent", "", kTProfile, {{80, 0, 80}});
125+
126+
registry.add("hEventCount", "Number of Event;; Count", {HistType::kTH1D, {{10, 0, 10}}});
127+
registry.get<TH1>(HIST("hEventCount"))->GetXaxis()->SetBinLabel(1, "Filtered event");
128+
registry.get<TH1>(HIST("hEventCount"))->GetXaxis()->SetBinLabel(2, "sel8");
129+
registry.get<TH1>(HIST("hEventCount"))->GetXaxis()->SetBinLabel(3, "occupancy");
130+
registry.get<TH1>(HIST("hEventCount"))->GetXaxis()->SetBinLabel(4, "kTVXinTRD");
131+
registry.get<TH1>(HIST("hEventCount"))->GetXaxis()->SetBinLabel(5, "kNoSameBunchPileup");
132+
registry.get<TH1>(HIST("hEventCount"))->GetXaxis()->SetBinLabel(6, "kIsGoodZvtxFT0vsPV");
133+
registry.get<TH1>(HIST("hEventCount"))->GetXaxis()->SetBinLabel(7, "kNoCollInTimeRangeStandard");
134+
registry.get<TH1>(HIST("hEventCount"))->GetXaxis()->SetBinLabel(8, "kIsVertexITSTPC");
135+
registry.get<TH1>(HIST("hEventCount"))->GetXaxis()->SetBinLabel(9, "after Mult cuts");
136+
registry.get<TH1>(HIST("hEventCount"))->GetXaxis()->SetBinLabel(10, "isSelected");
137+
138+
if (cfgUseAdditionalEventCut) {
139+
fMultPVCutLow = new TF1("fMultPVCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x - 3.5*([5]+[6]*x+[7]*x*x+[8]*x*x*x+[9]*x*x*x*x)", 0, 100);
140+
fMultPVCutLow->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06);
141+
fMultPVCutHigh = new TF1("fMultPVCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x + 3.5*([5]+[6]*x+[7]*x*x+[8]*x*x*x+[9]*x*x*x*x)", 0, 100);
142+
fMultPVCutHigh->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06);
143+
144+
fMultCutLow = new TF1("fMultCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x - 2.*([4]+[5]*x+[6]*x*x+[7]*x*x*x+[8]*x*x*x*x)", 0, 100);
145+
fMultCutLow->SetParameters(1654.46, -47.2379, 0.449833, -0.0014125, 150.773, -3.67334, 0.0530503, -0.000614061, 3.15956e-06);
146+
fMultCutHigh = new TF1("fMultCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x + 3.*([4]+[5]*x+[6]*x*x+[7]*x*x*x+[8]*x*x*x*x)", 0, 100);
147+
fMultCutHigh->SetParameters(1654.46, -47.2379, 0.449833, -0.0014125, 150.773, -3.67334, 0.0530503, -0.000614061, 3.15956e-06);
148+
}
149+
150+
if (cfgUseAdditionalTrackCut) {
151+
fPhiCutLow = new TF1("fPhiCutLow", "0.06/x+pi/18.0-0.06", 0, 100);
152+
fPhiCutHigh = new TF1("fPhiCutHigh", "0.1/x+pi/18.0+0.06", 0, 100);
153+
}
154+
}
155+
156+
int getMagneticField(uint64_t timestamp)
157+
{
158+
// TODO done only once (and not per run). Will be replaced by CCDBConfigurable
159+
// static o2::parameters::GRPObject* grpo = nullptr;
160+
static o2::parameters::GRPMagField* grpo = nullptr;
161+
if (grpo == nullptr) {
162+
// grpo = ccdb->getForTimeStamp<o2::parameters::GRPObject>("GLO/GRP/GRP", timestamp);
163+
grpo = ccdb->getForTimeStamp<o2::parameters::GRPMagField>("GLO/Config/GRPMagField", timestamp);
164+
if (grpo == nullptr) {
165+
LOGF(fatal, "GRP object not found for timestamp %llu", timestamp);
166+
return 0;
167+
}
168+
LOGF(info, "Retrieved GRP for timestamp %llu with magnetic field of %d kG", timestamp, grpo->getNominalL3Field());
169+
}
170+
return grpo->getNominalL3Field();
171+
}
172+
173+
template <typename TCollision>
174+
bool eventSelected(TCollision collision, const int& multTrk, const float& centrality)
175+
{
176+
if (cfgTVXinTRD) {
177+
if (collision.alias_bit(kTVXinTRD)) {
178+
// TRD triggered
179+
// "CMTVX-B-NOPF-TRD,minbias_TVX"
180+
return 0;
181+
}
182+
registry.fill(HIST("hEventCount"), 3.5);
183+
}
184+
185+
if (cfgNoSameBunchPileupCut) {
186+
if (!collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) {
187+
// rejects collisions which are associated with the same "found-by-T0" bunch crossing
188+
// https://indico.cern.ch/event/1396220/#1-event-selection-with-its-rof
189+
return 0;
190+
}
191+
registry.fill(HIST("hEventCount"), 4.5);
192+
}
193+
if (cfgIsGoodZvtxFT0vsPV) {
194+
if (!collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) {
195+
// removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference
196+
// use this cut at low multiplicities with caution
197+
return 0;
198+
}
199+
registry.fill(HIST("hEventCount"), 5.5);
200+
}
201+
if (cfgNoCollInTimeRangeStandard) {
202+
if (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) {
203+
// Rejection of the collisions which have other events nearby
204+
return 0;
205+
}
206+
registry.fill(HIST("hEventCount"), 6.5);
207+
}
208+
209+
if (cfgIsVertexITSTPC) {
210+
if (!collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) {
211+
// selects collisions with at least one ITS-TPC track, and thus rejects vertices built from ITS-only tracks
212+
return 0;
213+
}
214+
registry.fill(HIST("hEventCount"), 7.5);
215+
}
216+
217+
float vtxz = -999;
218+
if (collision.numContrib() > 1) {
219+
vtxz = collision.posZ();
220+
float zRes = TMath::Sqrt(collision.covZZ());
221+
if (zRes > 0.25 && collision.numContrib() < 20)
222+
vtxz = -999;
223+
}
224+
// auto multV0A = collision.multFV0A();
225+
// auto multT0A = collision.multFT0A();
226+
// auto multT0C = collision.multFT0C();
227+
auto multNTracksPV = collision.multNTracksPV();
228+
229+
if (vtxz > 10 || vtxz < -10)
230+
return 0;
231+
if (multNTracksPV < fMultPVCutLow->Eval(centrality))
232+
return 0;
233+
if (multNTracksPV > fMultPVCutHigh->Eval(centrality))
234+
return 0;
235+
if (multTrk < fMultCutLow->Eval(centrality))
236+
return 0;
237+
if (multTrk > fMultCutHigh->Eval(centrality))
238+
return 0;
239+
240+
registry.fill(HIST("hEventCount"), 8.5);
241+
242+
return 1;
243+
}
244+
245+
template <typename TTrack>
246+
bool trackSelected(TTrack track, const int& field)
247+
{
248+
double phimodn = track.phi();
249+
if (field < 0) // for negative polarity field
250+
phimodn = TMath::TwoPi() - phimodn;
251+
if (track.sign() < 0) // for negative charge
252+
phimodn = TMath::TwoPi() - phimodn;
253+
if (phimodn < 0)
254+
LOGF(warning, "phi < 0: %g", phimodn);
255+
256+
phimodn += TMath::Pi() / 18.0; // to center gap in the middle
257+
phimodn = fmod(phimodn, TMath::Pi() / 9.0);
258+
registry.fill(HIST("pt_phi_bef"), track.pt(), phimodn);
259+
if (phimodn < fPhiCutHigh->Eval(track.pt()) && phimodn > fPhiCutLow->Eval(track.pt()))
260+
return false; // reject track
261+
registry.fill(HIST("pt_phi_aft"), track.pt(), phimodn);
262+
return true;
263+
}
264+
265+
void process(myCollisions::iterator const& collision, aod::BCsWithTimestamps const&, myTracks const& tracks)
266+
{
267+
// Hier sum over collisions and get ZDC data.
268+
registry.fill(HIST("hEventCount"), .5);
269+
270+
if (!collision.sel8())
271+
return;
272+
registry.fill(HIST("hEventCount"), 1.5);
273+
274+
auto bc = collision.bc_as<aod::BCsWithTimestamps>();
275+
auto field = (cfgMagField == 99999) ? getMagneticField(bc.timestamp()) : cfgMagField;
276+
277+
auto centrality = collision.centFT0C();
278+
// auto bc = collision.template bc_as<aod::BCsWithTimestamps>();
279+
if (!eventSelected(collision, tracks.size(), centrality))
280+
return;
281+
282+
if (collision.isSelected()) {
283+
registry.fill(HIST("hEventCount"), 9.5);
284+
285+
registry.fill(HIST("hCent"), centrality);
286+
287+
double qxA = collision.qxA();
288+
double qyA = collision.qyA();
289+
double qxC = collision.qxC();
290+
double qyC = collision.qyC();
291+
292+
double Psi_A = 1.0 * TMath::ATan2(qyA, qxA);
293+
registry.fill(HIST("hSPplaneA"), Psi_A, 1);
294+
295+
double Psi_C = 1.0 * TMath::ATan2(qyC, qxC);
296+
registry.fill(HIST("hSPplaneC"), Psi_C, 1);
297+
298+
registry.fill(HIST("hSPplaneA-C"), Psi_A - Psi_C, 1);
299+
300+
registry.fill(HIST("hCosdPhi"), centrality, TMath::Cos(Psi_A - Psi_C));
301+
if (TMath::Cos(Psi_A - Psi_C) < 0)
302+
registry.fill(HIST("hSPlaneRes"), centrality, TMath::Sqrt(-1. * TMath::Cos(Psi_A - Psi_C)));
303+
registry.fill(HIST("hSindPhi"), centrality, TMath::Sin(Psi_A - Psi_C));
304+
305+
for (auto& track : tracks) {
306+
if (!trackSelected(track, field))
307+
continue;
308+
309+
double v1A = TMath::Cos(track.phi() - Psi_A);
310+
double v1C = TMath::Cos(track.phi() - Psi_C);
311+
312+
double v1AC = TMath::Cos(track.phi() - (Psi_A - Psi_C));
313+
314+
registry.fill(HIST("v1_eta"), track.eta(), (1. / TMath::Sqrt(2)) * (v1A - v1C));
315+
registry.fill(HIST("v1A_eta"), track.eta(), (v1A));
316+
registry.fill(HIST("v1C_eta"), track.eta(), (v1C));
317+
registry.fill(HIST("v1AC_eta"), track.eta(), (v1AC));
318+
319+
double v2A = TMath::Cos(2 * (track.phi() - Psi_A));
320+
double v2C = TMath::Cos(2 * (track.phi() - Psi_C));
321+
double v2AC = TMath::Cos(2 * (track.phi() - (Psi_A - Psi_C)));
322+
323+
registry.fill(HIST("v2_cent"), centrality, (1. / TMath::Sqrt(2)) * (v2A - v2C));
324+
registry.fill(HIST("v2A_cent"), centrality, (v2A));
325+
registry.fill(HIST("v2C_cent"), centrality, (v2C));
326+
registry.fill(HIST("v2AC_cent"), centrality, (v2AC));
327+
}
328+
329+
float qIm = collision.qvecIm()[0];
330+
float qRe = collision.qvecRe()[0];
331+
332+
registry.fill(HIST("hqIm"), qIm);
333+
registry.fill(HIST("hqRe"), qRe);
334+
}
335+
}
336+
};
337+
338+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
339+
{
340+
return WorkflowSpec{
341+
adaptAnalysisTask<flowAnalysisSP>(cfgc),
342+
};
343+
}

0 commit comments

Comments
 (0)