Skip to content

Commit 39a9c37

Browse files
cnkosteralibuild
andauthored
[PWGCF,Tutorial] Tutorial task for spectator plane CF (#13803)
Co-authored-by: ALICE Action Bot <alibuild@cern.ch>
1 parent 216f647 commit 39a9c37

File tree

2 files changed

+242
-0
lines changed

2 files changed

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

0 commit comments

Comments
 (0)