Skip to content

Commit ffb30be

Browse files
committed
Tutorial task for spectator plane CF
1 parent cd8205f commit ffb30be

File tree

2 files changed

+245
-0
lines changed

2 files changed

+245
-0
lines changed

Tutorials/PWGCF/EventPlane/src/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,8 @@ o2physics_add_dpl_workflow(qvectors-tutorial
1313
SOURCES qVectorstutorial.cxx
1414
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore
1515
COMPONENT_NAME Analysis)
16+
17+
o2physics_add_dpl_workflow(spectator-plane-tutorial
18+
SOURCES SpectatorPlaneTutorial.cxx
19+
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore
20+
COMPONENT_NAME Analysis)
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
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 SpectatorPlaneTutorial.cxx
13+
/// \author Noor Koster
14+
/// \since 11/2025
15+
/// \brief This is a tutorial task to show how to use the ZDC q-vectors and the spectator plane resolution.
16+
17+
18+
#include "PWGCF/DataModel/SPTableZDC.h"
19+
20+
#include "Common/Core/EventPlaneHelper.h"
21+
#include "Common/Core/RecoDecay.h"
22+
#include "Common/Core/TrackSelection.h"
23+
#include "Common/DataModel/Centrality.h"
24+
#include "Common/DataModel/EventSelection.h"
25+
#include "Common/DataModel/Multiplicity.h"
26+
#include "Common/DataModel/Qvectors.h"
27+
#include "Common/DataModel/TrackSelectionTables.h"
28+
29+
#include "CCDB/BasicCCDBManager.h"
30+
#include "DataFormatsParameters/GRPLHCIFData.h"
31+
#include "DataFormatsParameters/GRPMagField.h"
32+
#include "Framework/ASoAHelpers.h"
33+
#include "Framework/AnalysisTask.h"
34+
#include "Framework/HistogramRegistry.h"
35+
#include "Framework/RunningWorkflowInfo.h"
36+
#include "Framework/runDataProcessing.h"
37+
38+
#include "TF1.h"
39+
#include "TPDGCode.h"
40+
41+
#include <algorithm>
42+
#include <map>
43+
#include <numeric>
44+
#include <string>
45+
#include <unordered_map>
46+
#include <utility>
47+
#include <vector>
48+
49+
using namespace o2;
50+
using namespace o2::framework;
51+
using namespace o2::framework::expressions;
52+
using namespace o2::aod::rctsel;
53+
// using namespace o2::analysis;
54+
55+
#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable<TYPE> NAME{#NAME, DEFAULT, HELP};
56+
57+
struct SpectatorPlaneTutorial {
58+
RCTFlagsChecker rctChecker;
59+
60+
struct : ConfigurableGroup {
61+
O2_DEFINE_CONFIGURABLE(cfgEvtUseRCTFlagChecker, bool, false, "Evt sel: use RCT flag checker");
62+
O2_DEFINE_CONFIGURABLE(cfgEvtRCTFlagCheckerLabel, std::string, "CBT_hadronPID", "Evt sel: RCT flag checker label (CBT, CBT_hadronPID)"); // all Labels can be found in Common/CCDB/RCTSelectionFlags.h
63+
O2_DEFINE_CONFIGURABLE(cfgEvtRCTFlagCheckerZDCCheck, bool, false, "Evt sel: RCT flag checker ZDC check");
64+
O2_DEFINE_CONFIGURABLE(cfgEvtRCTFlagCheckerLimitAcceptAsBad, bool, false, "Evt sel: RCT flag checker treat Limited Acceptance As Bad");
65+
} rctFlags;
66+
67+
// settings for CCDB data
68+
O2_DEFINE_CONFIGURABLE(cfgCCDBdir_QQ, std::string, "Users/c/ckoster/ZDC/LHC23_PbPb_pass5/meanQQ/Default", "ccdb dir for average QQ values in 1% centrality bins");
69+
O2_DEFINE_CONFIGURABLE(cfgCCDBdir_SP, std::string, "Users/c/ckoster/ZDC/LHC23_zzh_pass4/SPPlaneRes", "ccdb dir for average event plane resolution in 1% centrality bins");
70+
// Confogirable axis
71+
ConfigurableAxis axisCentrality{"axisCentrality", {20, 0, 100}, "Centrality bins for vn "};
72+
73+
// Configurables containing vector
74+
75+
Filter collisionFilter = nabs(aod::collision::posZ) < 10.0f;
76+
Filter trackFilter = nabs(aod::track::eta) < 0.8f && aod::track::pt > 0.2f && aod::track::pt < 10.0f && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && nabs(aod::track::dcaXY) < 0.2f && nabs(aod::track::dcaZ) < 2.0f;
77+
using GeneralCollisions = soa::Join<aod::Collisions, aod::EvSels, aod::Mults, aod::CentFT0Cs>;
78+
using UnfilteredTracks = soa::Join<aod::Tracks, aod::TracksExtra, aod::TrackSelection, aod::TracksDCA>;
79+
80+
using UsedTracks = soa::Filtered<UnfilteredTracks>;
81+
using ZDCCollisions = soa::Filtered<soa::Join<GeneralCollisions, aod::SPTableZDC>>; // IMPORTANT: ZDCCollisions must be used to get access to ZDC q-vectors --> PWGCF/DataModel/SPTableZDC.h & PWGCF/Flow/TableProducer/zdcQVectors.cxx
82+
83+
// Connect to ccdb
84+
Service<ccdb::BasicCCDBManager> ccdb;
85+
86+
HistogramRegistry registry{"registry"};
87+
88+
void init(InitContext const&)
89+
{
90+
ccdb->setURL("http://alice-ccdb.cern.ch");
91+
ccdb->setCaching(true);
92+
ccdb->setLocalObjectValidityChecking();
93+
94+
int64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
95+
ccdb->setCreatedNotAfter(now);
96+
97+
98+
AxisSpec axisPhi = {60, 0, M_PI * 2, "#varphi"};
99+
AxisSpec axisEta = {64, -1.6, 1.6, "#eta"};
100+
AxisSpec axisEtaVn = {8, -.8, .8, "#eta"};
101+
AxisSpec axisVx = {40, -0.01, 0.01, "v_{x}"};
102+
AxisSpec axisVy = {40, -0.01, 0.01, "v_{y}"};
103+
AxisSpec axisVz = {40, -10, 10, "v_{z}"};
104+
AxisSpec axisCent = {90, 0, 90, "Centrality(%)"};
105+
AxisSpec axisPhiPlane = {100, -M_PI, M_PI, "#Psi"};
106+
AxisSpec axisQx = {100, -0.2, 0.2, "Q_{X}"};
107+
AxisSpec axisQy = {100, -0.2, 0.2, "Q_{Y}"};
108+
AxisSpec axisQQ = {100, -0.2, 0.2, "#LT Q_{X}^{A}Q_{Y}^{C} #GT"};
109+
110+
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};
111+
AxisSpec axisPt = {ptbinning, "#it{p}_{T} GeV/#it{c}"};
112+
113+
int ptbins = ptbinning.size() - 1;
114+
115+
rctChecker.init(rctFlags.cfgEvtRCTFlagCheckerLabel, rctFlags.cfgEvtRCTFlagCheckerZDCCheck, rctFlags.cfgEvtRCTFlagCheckerLimitAcceptAsBad);
116+
117+
registry.add("hCentrality", "Centrality; #Events; Centrality (%)", {HistType::kTH1D, {axisCent}});
118+
registry.add("hSPplaneA", "Spectator Plane Angle A; #Events; #Psi_{A}", {HistType::kTH1D, {axisPhiPlane}});
119+
registry.add("qAqCXY", "Qx ZDCA x Qy ZDCC vs cent ; #ltQ_{X}^{A}Q_{Y}^{C}#GT; Centrality (%)", {HistType::kTH2D, {axisCent, axisQQ}});
120+
// Add here the histograms for the spectator plane angle C
121+
// registry.add(.........)
122+
registry.add("hSPplaneAvsC", "Spectator Plane Angle A vs C; #Events; #Psi_{A}; #Psi_{C}", {HistType::kTH2D, {axisPhiPlane, axisPhiPlane}});
123+
registry.add("hSPplaneFull", "Spectator Plane Angle Full; #Events; #Psi_{Full}", {HistType::kTH1D, {axisPhiPlane}});
124+
125+
// Note: we will fill these with data from the CCDB, just to take a look!
126+
registry.add("CalibHistos/hQQx", "QQx; #Events; QQx", {HistType::kTProfile, {axisCent}});
127+
registry.add("CalibHistos/hQQy", "QQy; #Events; QQy", {HistType::kTProfile, {axisCent}});
128+
registry.add("CalibHistos/hQQ", "QQ; #Events; QQx + QQy", {HistType::kTProfile, {axisCent}});
129+
// Add here the histograms for the cross-terms of the Q-vectors from the ZDC
130+
131+
registry.add("CalibHistos/hEvPlaneRes", "Event Plane Resolution; #Events; Event Plane Resolution", {HistType::kTProfile, {axisCent}});
132+
133+
// Flow Histograms
134+
registry.add("flow/v1A", "", {HistType::kTProfile, {axisPt}});
135+
registry.add("flow/v1C", "", {HistType::kTProfile, {axisPt}});
136+
137+
registry.add("flow/vnAxCxUx_MH", "", {HistType::kTProfile, {axisCent}});
138+
registry.add("flow/vnAyCyUx_MH", "", {HistType::kTProfile, {axisCent}});
139+
registry.add("flow/vnAxCyUy_MH", "", {HistType::kTProfile, {axisCent}});
140+
registry.add("flow/vnAyCxUy_MH", "", {HistType::kTProfile, {axisCent}});
141+
}
142+
143+
144+
void process(ZDCCollisions::iterator const& collision, aod::BCsWithTimestamps const&, UsedTracks const& tracks)
145+
{
146+
147+
auto bc = collision.bc_as<aod::BCsWithTimestamps>();
148+
149+
float centrality = collision.centFT0C();
150+
registry.fill(HIST("hCentrality"), centrality);
151+
152+
if (centrality > 80 || centrality < 0)
153+
return;
154+
155+
if (collision.isSelected() == false)
156+
return;
157+
158+
// Get the ZDC q-vectors
159+
double qxA = collision.qxA();
160+
double qyA = collision.qyA();
161+
double qxC = collision.qxC();
162+
double qyC = collision.qyC();
163+
164+
// Calculate the spectator plane angles
165+
double psiA = 1.0 * std::atan2(qyA, qxA);
166+
registry.fill(HIST("hSPplaneA"), psiA);
167+
168+
// Add the PsiA vs PsiC as a TH2D
169+
170+
double psiC = 1.0 * std::atan2(qyC, qxC);
171+
double psiFull = 1.0 * std::atan2(qyA + qyC, qxA + qxC);
172+
registry.fill(HIST("hSPplaneFull"), psiFull);
173+
174+
registry.fill(HIST("hSPplaneAvsC"), psiA, psiC);
175+
176+
// Fill the q-vector correlations
177+
registry.fill(HIST("qAqCXY"), centrality, qxA * qxC + qyA * qyC);
178+
179+
double QQx = 1;
180+
double QQy = 1;
181+
double QQ = 1;
182+
double evPlaneRes = 1;
183+
184+
// Get QQ-correlations from CCDB
185+
if(cfgCCDBdir_QQ.value.empty() == false) {
186+
TList* list = ccdb->getForTimeStamp<TList>(cfgCCDBdir_QQ.value, bc.timestamp());
187+
TProfile* qAqCX = reinterpret_cast<TProfile*>(list->FindObject("qAqCX"));
188+
TProfile* qAqCY = reinterpret_cast<TProfile*>(list->FindObject("qAqCY"));
189+
TProfile* qAqCXY = reinterpret_cast<TProfile*>(list->FindObject("qAqCXY"));
190+
// The sum is qAqCXY
191+
QQx = qAqCX->GetBinContent(centrality);
192+
QQy = qAqCY->GetBinContent(centrality);
193+
QQ = qAqCXY->GetBinContent(centrality);
194+
registry.fill(HIST("CalibHistos/hQQx"), centrality, QQx);
195+
registry.fill(HIST("CalibHistos/hQQy"), centrality, QQy);
196+
registry.fill(HIST("CalibHistos/hQQ"), centrality, QQ);
197+
}
198+
// Get event plane resolution from CCDB
199+
if(cfgCCDBdir_SP.value.empty() == false) {
200+
evPlaneRes = ccdb->getForTimeStamp<TProfile>(cfgCCDBdir_SP.value, bc.timestamp())->GetBinContent(centrality);
201+
registry.fill(HIST("CalibHistos/hEvPlaneRes"), centrality, evPlaneRes);
202+
}
203+
204+
for (const auto& track : tracks) {
205+
206+
// constrain angle to 0 -> [0,0+2pi]
207+
auto phi = RecoDecay::constrainAngle(track.phi(), 0);
208+
209+
double ux = std::cos(phi);
210+
double uy = std::sin(phi);
211+
212+
double uxMH = std::cos(2 * phi);
213+
double uyMH = std::sin(2 * phi);
214+
215+
double v1A = (uy * qyA + ux * qxA) / std::sqrt(std::fabs(QQ));
216+
double v1C = (uy * qyC + ux * qxC) / std::sqrt(std::fabs(QQ));
217+
218+
double v2AxCxUx_MH = (uxMH * qxA * qxC) / QQx;
219+
double v2AyCyUx_MH = (uxMH * qyA * qyC) / QQy;
220+
double v2AxCyUy_MH = (uyMH * qxA * qyC) / QQx;
221+
double v2AyCxUy_MH = (uyMH * qyA * qxC) / QQy;
222+
223+
registry.fill(HIST("flow/v1A"), track.eta(), v1A);
224+
registry.fill(HIST("flow/v1C"), track.eta(), v1C);
225+
226+
registry.fill(HIST("flow/v2AxCxUx_MH"), centrality, v2AxCxUx_MH);
227+
registry.fill(HIST("flow/v2AyCyUx_MH"), centrality, v2AyCyUx_MH);
228+
registry.fill(HIST("flow/v2AxCyUy_MH"), centrality, v2AxCyUy_MH);
229+
registry.fill(HIST("flow/v2AyCxUy_MH"), centrality, v2AyCxUy_MH);
230+
231+
}
232+
}
233+
234+
};
235+
236+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
237+
{
238+
return WorkflowSpec{
239+
adaptAnalysisTask<SpectatorPlaneTutorial>(cfgc)};
240+
}

0 commit comments

Comments
 (0)