Skip to content

Commit f681d9c

Browse files
authored
[PWGUD] Add task for flow with dihadron correlation in UPC study (#10711)
1 parent f52589f commit f681d9c

File tree

2 files changed

+275
-1
lines changed

2 files changed

+275
-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: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
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+
using UdTracks = soa::Join<aod::UDTracks, aod::UDTracksExtra, aod::UDTracksPID>;
69+
using UdTracksFull = soa::Join<aod::UDTracks, aod::UDTracksPID, aod::UDTracksExtra, aod::UDTracksFlags, aod::UDTracksDCA>;
70+
using UDCollisionsFull = soa::Join<aod::UDCollisions, aod::SGCollisions, aod::UDCollisionsSels, aod::UDZdcsReduced>;
71+
72+
Produces<aod::Multiplicity> multiplicityNch;
73+
74+
HistogramRegistry registry{"registry"};
75+
76+
void init(InitContext&)
77+
{
78+
AxisSpec axisNch = {100, 0, 100};
79+
AxisSpec axisVrtx = {10, -10, 10};
80+
81+
registry.add("Ncharge", "N_{charge}", {HistType::kTH1D, {axisNch}});
82+
registry.add("zVtx_all", "zVtx_all", {HistType::kTH1D, {axisVrtx}});
83+
}
84+
85+
void process(UDCollisionsFull::iterator const& collision, UdTracksFull const& tracks)
86+
{
87+
multiplicityNch(tracks.size());
88+
registry.fill(HIST("Ncharge"), tracks.size());
89+
registry.fill(HIST("zVtx_all"), collision.posZ());
90+
}
91+
};
92+
93+
struct FlowCorrelationsUpc {
94+
O2_DEFINE_CONFIGURABLE(cfgZVtxCut, float, 10.0f, "Accepted z-vertex range")
95+
O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.2f, "minimum accepted track pT")
96+
O2_DEFINE_CONFIGURABLE(cfgPtCutMax, float, 10.0f, "maximum accepted track pT")
97+
O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.8f, "Eta cut")
98+
O2_DEFINE_CONFIGURABLE(cfgMinMixEventNum, int, 5, "Minimum number of events to mix")
99+
O2_DEFINE_CONFIGURABLE(cfgMinMult, int, 0, "Minimum multiplicity for collision")
100+
O2_DEFINE_CONFIGURABLE(cfgMaxMult, int, 10, "Maximum multiplicity for collision")
101+
102+
ConfigurableAxis axisVertex{"axisVertex", {10, -10, 10}, "vertex axis for histograms"};
103+
ConfigurableAxis axisEta{"axisEta", {40, -1., 1.}, "eta axis for histograms"};
104+
ConfigurableAxis axisPhi{"axisPhi", {72, 0.0, constants::math::TwoPI}, "phi axis for histograms"};
105+
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"};
106+
ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"};
107+
ConfigurableAxis axisDeltaEta{"axisDeltaEta", {40, -2, 2}, "delta eta axis for histograms"};
108+
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"};
109+
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"};
110+
ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 80, 100}, "multiplicity / centrality axis for histograms"};
111+
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"};
112+
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"};
113+
114+
ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {10, -10, 10}, "vertex axis for efficiency histograms"};
115+
ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {20, -1.0, 1.0}, "eta axis for efficiency histograms"};
116+
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"};
117+
118+
// Added UPC Cuts
119+
SGSelector sgSelector;
120+
Configurable<float> cfgCutFV0{"cfgCutFV0", 50., "FV0A threshold"};
121+
Configurable<float> cfgCutFT0A{"cfgCutFT0A", 150., "FT0A threshold"};
122+
Configurable<float> cfgCutFT0C{"cfgCutFT0C", 50., "FT0C threshold"};
123+
Configurable<float> cfgCutZDC{"cfgCutZDC", 10., "ZDC threshold"};
124+
Configurable<float> cfgGapSideSelection{"cfgGapSideSelection", 2, "gap selection"};
125+
126+
// make the filters and cuts.
127+
// Filter collisionFilter = (nabs(aod::collision::posZ) < cfgZVtxCut) && (aod::flowcorrupc::multiplicity) > cfgMinMult && (aod::flowcorrupc::multiplicity) < cfgMaxMult && (aod::evsel::sel8) == true;
128+
// Filter trackFilter = (nabs(aod::track::eta) < cfgEtaCut) && (aod::track::pt > cfgPtCutMin) && (aod::track::pt < cfgPtCutMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true));
129+
130+
using UdTracks = soa::Join<aod::UDTracks, aod::UDTracksExtra, aod::UDTracksPID>;
131+
using UdTracksFull = soa::Join<aod::UDTracks, aod::UDTracksPID, aod::UDTracksExtra, aod::UDTracksFlags, aod::UDTracksDCA>;
132+
using UDCollisionsFull = soa::Join<aod::UDCollisions, aod::SGCollisions, aod::UDCollisionsSels, aod::UDZdcsReduced, aod::Multiplicity>;
133+
134+
// Define the outputs
135+
OutputObj<CorrelationContainer> same{Form("sameEvent_%i_%i", static_cast<int>(cfgMinMult), static_cast<int>(cfgMaxMult))};
136+
OutputObj<CorrelationContainer> mixed{Form("mixedEvent_%i_%i", static_cast<int>(cfgMinMult), static_cast<int>(cfgMaxMult))};
137+
138+
HistogramRegistry registry{"registry"};
139+
140+
void init(InitContext&)
141+
{
142+
LOGF(info, "Starting init");
143+
// Make histograms to check the distributions after cuts
144+
registry.add("deltaEta_deltaPhi_same", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); // check to see the delta eta and delta phi distribution
145+
registry.add("deltaEta_deltaPhi_mixed", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}});
146+
registry.add("Phi", "Phi", {HistType::kTH1D, {axisPhi}});
147+
registry.add("Eta", "Eta", {HistType::kTH1D, {axisEta}});
148+
registry.add("pT", "pT", {HistType::kTH1D, {axisPtTrigger}});
149+
registry.add("Nch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}});
150+
registry.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}});
151+
152+
registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisMultiplicity, axisVertex, axisPtTrigger}}});
153+
154+
registry.add("eventcount", "bin", {HistType::kTH1F, {{3, 0, 3, "bin"}}}); // histogram to see how many events are in the same and mixed event
155+
156+
std::vector<AxisSpec> corrAxis = {{axisMultiplicity, "Nch"},
157+
{axisVertex, "z-vtx (cm)"},
158+
{axisPtTrigger, "p_{T} (GeV/c)"},
159+
{axisPtAssoc, "p_{T} (GeV/c)"},
160+
{axisDeltaPhi, "#Delta#varphi (rad)"},
161+
{axisDeltaEta, "#Delta#eta"}};
162+
std::vector<AxisSpec> effAxis = {
163+
{axisVertexEfficiency, "z-vtx (cm)"},
164+
{axisPtEfficiency, "p_{T} (GeV/c)"},
165+
{axisEtaEfficiency, "#eta"},
166+
};
167+
std::vector<AxisSpec> userAxis;
168+
169+
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));
170+
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));
171+
}
172+
enum EventType {
173+
SameEvent = 1,
174+
MixedEvent = 3
175+
};
176+
177+
// fill multiple histograms
178+
template <typename TCollision, typename TTracks>
179+
void fillYield(TCollision collision, TTracks tracks) // function to fill the yield and etaphi histograms.
180+
{
181+
registry.fill(HIST("Nch"), tracks.size());
182+
registry.fill(HIST("zVtx"), collision.posZ());
183+
184+
for (auto const& track1 : tracks) {
185+
auto momentum1 = std::array<double, 3>{track1.px(), track1.py(), track1.pz()};
186+
registry.fill(HIST("Phi"), RecoDecay::phi(momentum1));
187+
registry.fill(HIST("Eta"), RecoDecay::eta(momentum1));
188+
registry.fill(HIST("pT"), track1.pt());
189+
}
190+
}
191+
192+
template <CorrelationContainer::CFStep step, typename TTracks>
193+
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
194+
{
195+
// loop over all tracks
196+
for (auto const& track1 : tracks1) {
197+
198+
if (system == SameEvent) {
199+
registry.fill(HIST("Trig_hist"), Nch, posZ, track1.pt());
200+
}
201+
202+
for (auto const& track2 : tracks2) {
203+
204+
if (track1.pt() <= track2.pt())
205+
continue; // skip if the trigger pt is less than the associate p
206+
207+
auto momentum1 = std::array<double, 3>{track1.px(), track1.py(), track1.pz()};
208+
auto momentum2 = std::array<double, 3>{track2.px(), track2.py(), track2.pz()};
209+
double phi1 = RecoDecay::phi(momentum1);
210+
double phi2 = RecoDecay::phi(momentum2);
211+
float deltaPhi = RecoDecay::constrainAngle(phi1 - phi2, -PIHalf);
212+
float deltaEta = RecoDecay::eta(momentum1) - RecoDecay::eta(momentum2);
213+
214+
// fill the right sparse and histograms
215+
if (system == SameEvent) {
216+
same->getPairHist()->Fill(step, Nch, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta);
217+
registry.fill(HIST("deltaEta_deltaPhi_same"), deltaPhi, deltaEta);
218+
} else if (system == MixedEvent) {
219+
mixed->getPairHist()->Fill(step, Nch, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta);
220+
registry.fill(HIST("deltaEta_deltaPhi_mixed"), deltaPhi, deltaEta);
221+
}
222+
}
223+
}
224+
}
225+
226+
void processSame(UDCollisionsFull::iterator const& collision, UdTracksFull const& tracks)
227+
{
228+
int gapSide = collision.gapSide();
229+
if (gapSide < 0 || gapSide > 2) {
230+
return;
231+
}
232+
233+
int trueGapSide = sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC);
234+
gapSide = trueGapSide;
235+
if (gapSide == 2) {
236+
return;
237+
}
238+
239+
registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin
240+
fillYield(collision, tracks);
241+
fillCorrelations<CorrelationContainer::kCFStepReconstructed>(tracks, tracks, collision.posZ(), SameEvent, tracks.size()); // fill the SE histogram and Sparse
242+
}
243+
PROCESS_SWITCH(FlowCorrelationsUpc, processSame, "Process same event", true);
244+
245+
// event mixing
246+
247+
SliceCache cache;
248+
using MixedBinning = ColumnBinningPolicy<aod::collision::PosZ, aod::flowcorrupc::Multiplicity>;
249+
250+
// the process for filling the mixed events
251+
void processMixed(UDCollisionsFull const& collisions, UdTracksFull const& tracks)
252+
{
253+
MixedBinning binningOnVtxAndMult{{vtxMix, multMix}, true}; // true is for 'ignore overflows' (true by default)
254+
auto tracksTuple = std::make_tuple(tracks);
255+
SameKindPair<UDCollisionsFull, UdTracksFull, MixedBinning> pairs{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip
256+
257+
for (auto const& [collision1, tracks1, collision2, tracks2] : pairs) {
258+
registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin
259+
fillCorrelations<CorrelationContainer::kCFStepReconstructed>(tracks1, tracks2, collision1.posZ(), MixedEvent, tracks1.size());
260+
}
261+
}
262+
PROCESS_SWITCH(FlowCorrelationsUpc, processMixed, "Process mixed events", true);
263+
};
264+
265+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
266+
{
267+
return WorkflowSpec{
268+
adaptAnalysisTask<CalcNchUpc>(cfgc),
269+
adaptAnalysisTask<FlowCorrelationsUpc>(cfgc),
270+
};
271+
}

0 commit comments

Comments
 (0)