Skip to content

Commit a30258a

Browse files
committed
Add task for flow with dihadron correlation study
1 parent c3e50f5 commit a30258a

File tree

2 files changed

+268
-1
lines changed

2 files changed

+268
-1
lines changed

PWGUD/Tasks/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,4 +244,7 @@ o2physics_add_dpl_workflow(flow-cumulants-upc
244244
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::GFWCore
245245
COMPONENT_NAME Analysis)
246246

247-
247+
o2physics_add_dpl_workflow(flow-correlations-upc
248+
SOURCES flowCorrelationsUpc.cxx
249+
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGCFCore
250+
COMPONENT_NAME Analysis)
Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
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 flowCorrelationsUpc.cxx
13+
/// \brief Provides a sparse with usefull two particle correlation info
14+
/// \author Mingrui Zhao (mingrui.zhao@cern.ch, mingrui.zhao@mail.labz0.org)
15+
/// copied from Thor Jensen (thor.kjaersgaard.jensen@cern.ch) and Debojit Sarkar (debojit.sarkar@cern.ch)
16+
17+
#include <vector>
18+
19+
#include "Framework/runDataProcessing.h"
20+
#include "Framework/AnalysisTask.h"
21+
#include "Framework/AnalysisDataModel.h"
22+
#include "Framework/ASoAHelpers.h"
23+
#include "Framework/ASoA.h"
24+
#include "Framework/HistogramRegistry.h"
25+
#include "Framework/RunningWorkflowInfo.h"
26+
#include "CommonConstants/MathConstants.h"
27+
#include "CCDB/BasicCCDBManager.h"
28+
#include "Common/Core/RecoDecay.h"
29+
30+
#include "PWGUD/DataModel/UDTables.h"
31+
#include "PWGUD/Core/SGSelector.h"
32+
33+
#include "Common/DataModel/EventSelection.h"
34+
#include "Common/DataModel/TrackSelectionTables.h"
35+
#include "Common/DataModel/Centrality.h"
36+
#include "Common/DataModel/Multiplicity.h"
37+
#include "PWGCF/DataModel/CorrelationsDerived.h"
38+
#include "PWGCF/Core/CorrelationContainer.h"
39+
#include "PWGCF/Core/PairCuts.h"
40+
41+
namespace o2::aod
42+
{
43+
namespace flowcorrupc
44+
{
45+
DECLARE_SOA_COLUMN(Multiplicity, multiplicity, int);
46+
}
47+
DECLARE_SOA_TABLE(Multiplicity, "AOD", "MULTIPLICITY",
48+
flowcorrupc::Multiplicity);
49+
50+
} // namespace o2::aod
51+
52+
using namespace o2;
53+
using namespace o2::framework;
54+
using namespace o2::framework::expressions;
55+
56+
// define the filtered collisions and tracks
57+
#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable<TYPE> NAME{#NAME, DEFAULT, HELP};
58+
59+
struct CalcNchUpc {
60+
O2_DEFINE_CONFIGURABLE(cfgZVtxCut, float, 10.0f, "Accepted z-vertex range")
61+
O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.2f, "minimum accepted track pT")
62+
O2_DEFINE_CONFIGURABLE(cfgPtCutMax, float, 10.0f, "maximum accepted track pT")
63+
O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.8f, "Eta cut")
64+
O2_DEFINE_CONFIGURABLE(cfgMinMixEventNum, int, 5, "Minimum number of events to mix")
65+
66+
// Filter trackFilter = (nabs(aod::track::eta) < cfgEtaCut) && (aod::track::pt > cfgPtCutMin) && (aod::track::pt < cfgPtCutMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true));
67+
68+
69+
using UdTracks = soa::Join<aod::UDTracks, aod::UDTracksExtra, aod::UDTracksPID>;
70+
using UdTracksFull = soa::Join<aod::UDTracks, aod::UDTracksPID, aod::UDTracksExtra, aod::UDTracksFlags, aod::UDTracksDCA>;
71+
using UDCollisionsFull = soa::Join<aod::UDCollisions, aod::SGCollisions, aod::UDCollisionsSels, aod::UDZdcsReduced>;
72+
73+
Produces<aod::Multiplicity> multiplicityNch;
74+
75+
HistogramRegistry registry{"registry"};
76+
77+
void init(InitContext&)
78+
{
79+
AxisSpec axisNch = {100, 0, 100};
80+
AxisSpec axisVrtx = {10, -10, 10};
81+
82+
registry.add("Ncharge", "N_{charge}", {HistType::kTH1D, {axisNch}});
83+
registry.add("zVtx_all", "zVtx_all", {HistType::kTH1D, {axisVrtx}});
84+
}
85+
86+
void process(UDCollisionsFull::iterator const& collision, UdTracksFull const& tracks)
87+
{
88+
multiplicityNch(tracks.size());
89+
registry.fill(HIST("Ncharge"), tracks.size());
90+
registry.fill(HIST("zVtx_all"), collision.posZ());
91+
}
92+
};
93+
94+
struct FlowCorrelationsUpc {
95+
O2_DEFINE_CONFIGURABLE(cfgZVtxCut, float, 10.0f, "Accepted z-vertex range")
96+
O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.2f, "minimum accepted track pT")
97+
O2_DEFINE_CONFIGURABLE(cfgPtCutMax, float, 10.0f, "maximum accepted track pT")
98+
O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.8f, "Eta cut")
99+
O2_DEFINE_CONFIGURABLE(cfgMinMixEventNum, int, 5, "Minimum number of events to mix")
100+
O2_DEFINE_CONFIGURABLE(cfgMinMult, int, 0, "Minimum multiplicity for collision")
101+
O2_DEFINE_CONFIGURABLE(cfgMaxMult, int, 10, "Maximum multiplicity for collision")
102+
103+
ConfigurableAxis axisVertex{"axisVertex", {10, -10, 10}, "vertex axis for histograms"};
104+
ConfigurableAxis axisEta{"axisEta", {40, -1., 1.}, "eta axis for histograms"};
105+
ConfigurableAxis axisPhi{"axisPhi", {72, 0.0, constants::math::TwoPI}, "phi axis for histograms"};
106+
ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt axis for histograms"};
107+
ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"};
108+
ConfigurableAxis axisDeltaEta{"axisDeltaEta", {40, -2, 2}, "delta eta axis for histograms"};
109+
ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt trigger axis for histograms"};
110+
ConfigurableAxis axisPtAssoc{"axisPtAssoc", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt associated axis for histograms"};
111+
ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 80, 100}, "multiplicity / centrality axis for histograms"};
112+
ConfigurableAxis vtxMix{"vtxMix", {VARIABLE_WIDTH, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "vertex axis for mixed event histograms"};
113+
ConfigurableAxis multMix{"multMix", {VARIABLE_WIDTH, 0, 5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 80, 100}, "multiplicity / centrality axis for mixed event histograms"};
114+
115+
ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {10, -10, 10}, "vertex axis for efficiency histograms"};
116+
ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {20, -1.0, 1.0}, "eta axis for efficiency histograms"};
117+
ConfigurableAxis axisPtEfficiency{"axisPtEfficiency", {VARIABLE_WIDTH, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0}, "pt axis for efficiency histograms"};
118+
119+
// make the filters and cuts.
120+
// Filter collisionFilter = (nabs(aod::collision::posZ) < cfgZVtxCut) && (aod::flowcorrupc::multiplicity) > cfgMinMult && (aod::flowcorrupc::multiplicity) < cfgMaxMult && (aod::evsel::sel8) == true;
121+
// Filter trackFilter = (nabs(aod::track::eta) < cfgEtaCut) && (aod::track::pt > cfgPtCutMin) && (aod::track::pt < cfgPtCutMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true));
122+
123+
using UdTracks = soa::Join<aod::UDTracks, aod::UDTracksExtra, aod::UDTracksPID>;
124+
using UdTracksFull = soa::Join<aod::UDTracks, aod::UDTracksPID, aod::UDTracksExtra, aod::UDTracksFlags, aod::UDTracksDCA>;
125+
using UDCollisionsFull = soa::Join<aod::UDCollisions, aod::SGCollisions, aod::UDCollisionsSels, aod::UDZdcsReduced, aod::Multiplicity>;
126+
127+
// Define the outputs
128+
OutputObj<CorrelationContainer> same{Form("sameEvent_%i_%i", static_cast<int>(cfgMinMult), static_cast<int>(cfgMaxMult))};
129+
OutputObj<CorrelationContainer> mixed{Form("mixedEvent_%i_%i", static_cast<int>(cfgMinMult), static_cast<int>(cfgMaxMult))};
130+
131+
HistogramRegistry registry{"registry"};
132+
133+
void init(InitContext&)
134+
{
135+
LOGF(info, "Starting init");
136+
// Make histograms to check the distributions after cuts
137+
registry.add("deltaEta_deltaPhi_same", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); // check to see the delta eta and delta phi distribution
138+
registry.add("deltaEta_deltaPhi_mixed", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}});
139+
registry.add("Phi", "Phi", {HistType::kTH1D, {axisPhi}});
140+
registry.add("Eta", "Eta", {HistType::kTH1D, {axisEta}});
141+
registry.add("pT", "pT", {HistType::kTH1D, {axisPtTrigger}});
142+
registry.add("Nch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}});
143+
registry.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}});
144+
145+
registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisMultiplicity, axisVertex, axisPtTrigger}}});
146+
147+
registry.add("eventcount", "bin", {HistType::kTH1F, {{3, 0, 3, "bin"}}}); // histogram to see how many events are in the same and mixed event
148+
149+
std::vector<AxisSpec> corrAxis = {{axisMultiplicity, "Nch"},
150+
{axisVertex, "z-vtx (cm)"},
151+
{axisPtTrigger, "p_{T} (GeV/c)"},
152+
{axisPtAssoc, "p_{T} (GeV/c)"},
153+
{axisDeltaPhi, "#Delta#varphi (rad)"},
154+
{axisDeltaEta, "#Delta#eta"}};
155+
std::vector<AxisSpec> effAxis = {
156+
{axisVertexEfficiency, "z-vtx (cm)"},
157+
{axisPtEfficiency, "p_{T} (GeV/c)"},
158+
{axisEtaEfficiency, "#eta"},
159+
};
160+
std::vector<AxisSpec> userAxis;
161+
162+
same.setObject(new CorrelationContainer(Form("sameEvent_%i_%i", static_cast<int>(cfgMinMult), static_cast<int>(cfgMaxMult)), Form("sameEvent_%i_%i", static_cast<int>(cfgMinMult), static_cast<int>(cfgMaxMult)), corrAxis, effAxis, userAxis));
163+
mixed.setObject(new CorrelationContainer(Form("mixedEvent_%i_%i", static_cast<int>(cfgMinMult), static_cast<int>(cfgMaxMult)), Form("mixedEvent_%i_%i", static_cast<int>(cfgMinMult), static_cast<int>(cfgMaxMult)), corrAxis, effAxis, userAxis));
164+
}
165+
enum EventType {
166+
SameEvent = 1,
167+
MixedEvent = 3
168+
};
169+
170+
// fill multiple histograms
171+
template <typename TCollision, typename TTracks>
172+
void fillYield(TCollision collision, TTracks tracks) // function to fill the yield and etaphi histograms.
173+
{
174+
registry.fill(HIST("Nch"), tracks.size());
175+
registry.fill(HIST("zVtx"), collision.posZ());
176+
177+
for (auto const& track1 : tracks) {
178+
auto momentum1 = std::array<double, 3>{track1.px(), track1.py(), track1.pz()};
179+
registry.fill(HIST("Phi"), RecoDecay::phi(momentum1));
180+
registry.fill(HIST("Eta"), RecoDecay::eta(momentum1));
181+
registry.fill(HIST("pT"), track1.pt());
182+
}
183+
}
184+
185+
template <CorrelationContainer::CFStep step, typename TTracks>
186+
void fillCorrelations(TTracks tracks1, TTracks tracks2, float posZ, int system, float Nch) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms
187+
{
188+
// loop over all tracks
189+
for (auto const& track1 : tracks1) {
190+
191+
if (system == SameEvent) {
192+
registry.fill(HIST("Trig_hist"), Nch, posZ, track1.pt());
193+
}
194+
195+
for (auto const& track2 : tracks2) {
196+
197+
if (track1.pt() <= track2.pt())
198+
continue; // skip if the trigger pt is less than the associate p
199+
200+
auto momentum1 = std::array<double, 3>{track1.px(), track1.py(), track1.pz()};
201+
auto momentum2 = std::array<double, 3>{track2.px(), track2.py(), track2.pz()};
202+
double phi1 = RecoDecay::phi(momentum1);
203+
double phi2 = RecoDecay::phi(momentum2);
204+
float deltaPhi = RecoDecay::constrainAngle(phi1-phi2, -PIHalf);
205+
float deltaEta = RecoDecay::eta(momentum1) - RecoDecay::eta(momentum2);
206+
207+
// fill the right sparse and histograms
208+
if (system == SameEvent) {
209+
same->getPairHist()->Fill(step, Nch, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta);
210+
registry.fill(HIST("deltaEta_deltaPhi_same"), deltaPhi, deltaEta);
211+
} else if (system == MixedEvent) {
212+
mixed->getPairHist()->Fill(step, Nch, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta);
213+
registry.fill(HIST("deltaEta_deltaPhi_mixed"), deltaPhi, deltaEta);
214+
}
215+
}
216+
}
217+
}
218+
219+
void processSame(UDCollisionsFull::iterator const& collision, UdTracksFull const& tracks)
220+
{
221+
int gapSide = collision.gapSide();
222+
if (gapSide < 0 || gapSide > 2) {
223+
return;
224+
}
225+
226+
int trueGapSide = sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC);
227+
gapSide = trueGapSide;
228+
if (gapSide == 2) {
229+
return;
230+
}
231+
232+
registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin
233+
fillYield(collision, tracks);
234+
fillCorrelations<CorrelationContainer::kCFStepReconstructed>(tracks, tracks, collision.posZ(), SameEvent, tracks.size()); // fill the SE histogram and Sparse
235+
}
236+
PROCESS_SWITCH(FlowCorrelationsUpc, processSame, "Process same event", true);
237+
238+
// event mixing
239+
240+
SliceCache cache;
241+
using MixedBinning = ColumnBinningPolicy<aod::collision::PosZ, aod::flowcorrupc::Multiplicity>;
242+
243+
// the process for filling the mixed events
244+
void processMixed(UDCollisionsFull const& collisions, UdTracksFull const& tracks)
245+
{
246+
MixedBinning binningOnVtxAndMult{{vtxMix, multMix}, true}; // true is for 'ignore overflows' (true by default)
247+
auto tracksTuple = std::make_tuple(tracks);
248+
SameKindPair<UDCollisionsFull, UdTracksFull, MixedBinning> pairs{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip
249+
250+
for (auto const& [collision1, tracks1, collision2, tracks2] : pairs) {
251+
registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin
252+
fillCorrelations<CorrelationContainer::kCFStepReconstructed>(tracks1, tracks2, collision1.posZ(), MixedEvent, tracks1.size());
253+
}
254+
}
255+
PROCESS_SWITCH(FlowCorrelationsUpc, processMixed, "Process mixed events", true);
256+
};
257+
258+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
259+
{
260+
return WorkflowSpec{
261+
adaptAnalysisTask<CalcNchUpc>(cfgc),
262+
adaptAnalysisTask<FlowCorrelationsUpc>(cfgc),
263+
};
264+
}

0 commit comments

Comments
 (0)