Skip to content

Commit 7ec2d8c

Browse files
ariedel-cernAntonRiedelalibuild
authored
[PWGCF] Fix q-vector and event plane calculation in femto frame work (#17931)
Co-authored-by: Anton Riedel <anton.riedel@tum.de> Co-authored-by: ALICE Action Bot <alibuild@cern.ch>
1 parent ac5900e commit 7ec2d8c

5 files changed

Lines changed: 64 additions & 32 deletions

File tree

PWGCF/Femto/Core/collisionBuilder.h

Lines changed: 56 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ struct ConfCollisionBits : o2::framework::ConfigurableGroup {
8181
o2::framework::Configurable<std::vector<float>> sphericityMin{"sphericityMin", {}, "Minimum sphericity"};
8282
o2::framework::Configurable<std::vector<float>> sphericityMax{"sphericityMax", {}, "Maximum sphericity"};
8383
o2::framework::Configurable<std::vector<std::string>> triggers{"triggers", {}, "List of all triggers to be used"};
84-
o2::framework::Configurable<datatypes::QvecDetectorType> qvecDetector{"qvecDetector", 0, "Detector used to estimate the Q-vector: 0 -> FT0C, 1 -> FT0A"};
84+
o2::framework::Configurable<datatypes::EventShapeDetectorType> eventPlaneAngleDetector{"eventPlaneAngleDetector", 0, "Detector used to estimate the event plane angle: 0 -> FT0C, 1 -> FT0A"};
85+
o2::framework::Configurable<datatypes::EventShapeDetectorType> qvecDetector{"qvecDetector", 0, "Detector used to estimate the Q-vector: 0 -> FT0C, 1 -> FT0A"};
8586
o2::framework::Configurable<datatypes::QvecHarmonicType> qvecHarmonic{"qvecHarmonic", 2, "Harmonic n of the Q-vector and event plane angle Psi_n: 2 -> elliptic, 3 -> triangular"};
8687
};
8788

@@ -204,7 +205,7 @@ class CollisionSelection : public baseselection::BaseSelection<float, o2::analys
204205
/// trigger (Zorro) setup, and the selection bitmask.
205206
/// \param registry Histogram registry.
206207
/// \param filter ConfCollisionFilters (kinematic/quality pre-filter bounds).
207-
/// \param config ConfCollisionBits (selection bits + trigger list).
208+
/// \param config ConfCollisionBits (selection bits + trigger list + event shape settings).
208209
/// \param confRct ConfCollisionRctFlags (RCT flag checker configuration).
209210
/// \param confCcdb ConfCcdb (needed for the trigger CCDB path).
210211
template <typename T1, typename T2, typename T3, typename T4>
@@ -244,13 +245,19 @@ class CollisionSelection : public baseselection::BaseSelection<float, o2::analys
244245
}
245246

246247
// event shape
247-
mQvecDetector = static_cast<modes::QvecDetector>(config.qvecDetector.value);
248-
if (mQvecDetector >= modes::QvecDetector::kQvecDetectorLast) {
249-
LOG(fatal) << "Qvector Detector is not supported";
248+
mEventPlaneAngleDetector = static_cast<modes::EventShapeDetector>(config.eventPlaneAngleDetector.value);
249+
if (mEventPlaneAngleDetector >= modes::EventShapeDetector::kEventShapeDetectorLast) {
250+
LOG(fatal) << "Detector " << static_cast<int>(mEventPlaneAngleDetector) << " for event plane angle is not supported";
250251
}
252+
253+
mQvecDetector = static_cast<modes::EventShapeDetector>(config.qvecDetector.value);
254+
if (mQvecDetector >= modes::EventShapeDetector::kEventShapeDetectorLast) {
255+
LOG(fatal) << "Detector " << static_cast<int>(mQvecDetector) << " for q-vector is not supported";
256+
}
257+
251258
mQvecHarmonic = static_cast<modes::QvecHarmonic>(config.qvecHarmonic.value);
252259
if (mQvecHarmonic < modes::QvecHarmonic::kN2 || mQvecHarmonic >= modes::QvecHarmonic::kQvecHarmonicLast) {
253-
LOG(fatal) << "Qvector Harmonic is not supported";
260+
LOG(fatal) << "Harmonic " << static_cast<int>(mQvecHarmonic) << " is not supported";
254261
}
255262

256263
this->addSelection(kSel8, collisionSelectionNames.at(kSel8), config.sel8.value);
@@ -358,43 +365,40 @@ class CollisionSelection : public baseselection::BaseSelection<float, o2::analys
358365
}
359366
[[nodiscard]] float getMultiplicity() const { return mMultiplicity; }
360367

368+
/// \brief Reduced flow vector |q_n| = |Q_n| * sqrt(M) for the configured detector and harmonic
361369
template <modes::System system, typename T>
362370
void setQvector(T const& col)
363371
{
372+
const auto index = static_cast<std::size_t>(static_cast<int>(mQvecHarmonic) - 2); // n=2 -> 0, n=3 -> 1
364373
switch (mQvecDetector) {
365-
case modes::QvecDetector::kFT0C:
366-
mQvec = std::hypot(col.qvecFT0CReVec()[0], col.qvecFT0CImVec()[0]) * std::sqrt(col.sumAmplFT0C());
367-
break;
368-
case modes::QvecDetector::kFT0A:
369-
mQvec = std::hypot(col.qvecFT0AReVec()[0], col.qvecFT0AImVec()[0]) * std::sqrt(col.sumAmplFT0A());
374+
case modes::EventShapeDetector::kFT0C:
375+
mQvec = computeReducedQvec(col.qvecFT0CReVec(), col.qvecFT0CImVec(), col.sumAmplFT0C(), index);
370376
break;
371-
case modes::QvecDetector::kQvecDetectorLast:
372-
LOG(fatal) << "Invalid Q-vector detector";
377+
case modes::EventShapeDetector::kFT0A:
378+
mQvec = computeReducedQvec(col.qvecFT0AReVec(), col.qvecFT0AImVec(), col.sumAmplFT0A(), index);
373379
break;
374380
default:
375-
LOG(fatal) << "Invalid Q-vector detector";
381+
LOG(fatal) << "Invalid detector for q-vector";
376382
break;
377383
}
378384
}
379385
[[nodiscard]] float getQvector() const { return mQvec; }
380386

387+
/// \brief Event plane angle Psi_n in [0, 2pi/n) for the configured detector and harmonic
381388
template <modes::System system, typename T>
382389
void setEventPlane(T const& col)
383390
{
384-
auto harmonic = static_cast<float>(mQvecHarmonic);
385-
int index = static_cast<int>(mQvecHarmonic) - 2; // get index in the qvector vector
386-
switch (mQvecDetector) {
387-
case modes::QvecDetector::kFT0C:
388-
mEventPlane = RecoDecay::constrainAngle((std::atan2(col.qvecFT0CImVec()[index], col.qvecFT0CReVec()[index])) / harmonic, 0, harmonic); // constrain between 0 and 2pi/harmonic
389-
break;
390-
case modes::QvecDetector::kFT0A:
391-
mEventPlane = RecoDecay::constrainAngle((std::atan2(col.qvecFT0AImVec()[index], col.qvecFT0AReVec()[index])) / harmonic, 0, harmonic); // constrain between 0 and 2pi/harmonic
391+
const int harmonic = static_cast<int>(mQvecHarmonic);
392+
const auto index = static_cast<std::size_t>(harmonic - 2); // n=2 -> 0, n=3 -> 1
393+
switch (mEventPlaneAngleDetector) {
394+
case modes::EventShapeDetector::kFT0C:
395+
mEventPlane = computeEventPlane(col.qvecFT0CReVec(), col.qvecFT0CImVec(), index, harmonic);
392396
break;
393-
case modes::QvecDetector::kQvecDetectorLast:
394-
LOG(fatal) << "Invalid Q-vector detector";
397+
case modes::EventShapeDetector::kFT0A:
398+
mEventPlane = computeEventPlane(col.qvecFT0AReVec(), col.qvecFT0AImVec(), index, harmonic);
395399
break;
396400
default:
397-
LOG(fatal) << "Invalid Q-vector detector";
401+
LOG(fatal) << "Invalid detector for event plane angle";
398402
break;
399403
}
400404
}
@@ -527,6 +531,30 @@ class CollisionSelection : public baseselection::BaseSelection<float, o2::analys
527531
return static_cast<float>(2. * lambda2 / (lambda1 + lambda2));
528532
}
529533

534+
/// \brief |q_n| = |Q_n| * sqrt(M); returns 0 for non-positive amplitude sum to avoid NaN
535+
template <typename TRe, typename TIm>
536+
static float computeReducedQvec(TRe const& re, TIm const& im, float sumAmpl, std::size_t index)
537+
{
538+
if (index >= re.size() || index >= im.size()) {
539+
LOG(fatal) << "Requested Q-vector harmonic index " << index << " but only " << re.size() << " harmonics are stored";
540+
}
541+
if (!(sumAmpl > 0.f)) {
542+
return 0.f;
543+
}
544+
return static_cast<float>(std::hypot(re[index], im[index]) * std::sqrt(sumAmpl));
545+
}
546+
547+
/// \brief Psi_n = atan2(Im Q_n, Re Q_n) / n, constrained to [0, 2pi/n)
548+
template <typename TRe, typename TIm>
549+
static float computeEventPlane(TRe const& re, TIm const& im, std::size_t index, int harmonic)
550+
{
551+
if (index >= re.size() || index >= im.size()) {
552+
LOG(fatal) << "Requested Q-vector harmonic index " << index << " but only " << re.size() << " harmonics are stored";
553+
}
554+
const double psi = std::atan2(static_cast<double>(im[index]), static_cast<double>(re[index])) / static_cast<double>(harmonic);
555+
return static_cast<float>(RecoDecay::constrainAngle(psi, 0., static_cast<unsigned int>(harmonic)));
556+
}
557+
530558
// filter cuts
531559
float mVtxZMin = -12.f;
532560
float mVtxZMax = 12.f;
@@ -546,7 +574,9 @@ class CollisionSelection : public baseselection::BaseSelection<float, o2::analys
546574
float mQvec = 0.f;
547575
float mEventPlane = 0.f;
548576

549-
modes::QvecDetector mQvecDetector = modes::QvecDetector::kFT0C;
577+
// event shape
578+
modes::EventShapeDetector mEventPlaneAngleDetector = modes::EventShapeDetector::kFT0C;
579+
modes::EventShapeDetector mQvecDetector = modes::EventShapeDetector::kFT0C;
550580
modes::QvecHarmonic mQvecHarmonic = modes::QvecHarmonic::kN2;
551581

552582
// RCT flags

PWGCF/Femto/Core/collisionHistManager.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ constexpr std::array<histmanager::HistInfo<ColHist>, kColHistLast> HistTable = {
8989
{kCentVsSphericity, o2::framework::HistType::kTH2F, "hCentVsSphericity", "Centrality vs Sphericity; Centrality (%); Sphericity"},
9090
{kFT0AvsFT0C, o2::framework::HistType::kTH2F, "hFT0AvsFT0C", "FT0A centrality vs FT0C centrality; Centrality_{FT0A} (%); Centrality_{FT0C}"},
9191
// event shape
92-
{kQvector, o2::framework::HistType::kTH1F, "hQvector", "Q-vector; Q-vector; Entries"},
93-
{kEventPlaneAngle, o2::framework::HistType::kTH1F, "hEventPlaneAngle", "Event Plane angle; #Psi_{n}; Entries"},
92+
{kQvector, o2::framework::HistType::kTH1F, "hQvector", "q-vector; q-vector; Entries"},
93+
{kEventPlaneAngle, o2::framework::HistType::kTH1F, "hEventPlaneAngle", "Event Plane angle; #Psi_{EP}; Entries"},
9494
// mc
9595
{kTruePosZ, o2::framework::HistType::kTH1F, "hTruePosZ", "True vertex Z (mc-truth collision); V_{Z,True} (cm); Entries"},
9696
{kTrueCent, o2::framework::HistType::kTH1F, "hTrueCent", "True centrality (mc-truth collision); Centrality_{True} (%); Entries"},

PWGCF/Femto/Core/dataTypes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ using CharmHadronMaskType = uint32_t;
6464
using CharmHadronType = uint16_t;
6565

6666
// datatypes for event shape enums
67-
using QvecDetectorType = uint8_t;
67+
using EventShapeDetectorType = uint8_t;
6868
using QvecHarmonicType = uint8_t;
6969

7070
// datatype for kinematic variable

PWGCF/Femto/Core/modes.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#ifndef PWGCF_FEMTO_CORE_MODES_H_
1717
#define PWGCF_FEMTO_CORE_MODES_H_
1818

19+
#include "dataTypes.h"
20+
1921
#include "PWGCF/Femto/Core/dataTypes.h"
2022

2123
#include <cstdint>
@@ -178,10 +180,10 @@ enum class CharmHadron : o2::analysis::femto::datatypes::CharmHadronType {
178180
kLcBar
179181
};
180182

181-
enum class QvecDetector : o2::analysis::femto::datatypes::QvecDetectorType {
183+
enum class EventShapeDetector : o2::analysis::femto::datatypes::EventShapeDetectorType {
182184
kFT0C = 0,
183185
kFT0A = 1,
184-
kQvecDetectorLast = 2
186+
kEventShapeDetectorLast = 2
185187
};
186188

187189
enum class QvecHarmonic : o2::analysis::femto::datatypes::QvecHarmonicType {

PWGCF/Femto/Core/pairHistManager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ constexpr std::array<histmanager::HistInfo<PairHist>, kPairHistogramLast>
363363
{kTrueQoutVsQout, o2::framework::HistType::kTH2F, "hTrueQoutVsQout", "q_{out,True} vs q_{out}; q_{out,True} (GeV/#it{c}); q_{out} (GeV/#it{c})"},
364364
{kTrueQsideVsQside, o2::framework::HistType::kTH2F, "hTrueQsideVsQside", "q_{side,True} vs q_{side}; q_{side,True} (GeV/#it{c}); q_{side} (GeV/#it{c})"},
365365
{kTrueQlongVsQlong, o2::framework::HistType::kTH2F, "hTrueQlongVsQlong", "q_{long,True} vs q_{long}; q_{long,True} (GeV/#it{c}); q_{long} (GeV/#it{c})"},
366-
{kQoutVsQsideVsQlongVsMtVsCentVsEventPlaneAngleVsQvector, o2::framework::HistType::kTHnSparseF, "hQoutQsideQlongEventPlaneAngleQvector", "Event shape enginering; q_{out} (GeV/#it{c}); q_{side} (GeV/#it{c}); q_{long} (GeV/#it{c}); #varphi_{EP}; q-vector;"},
366+
{kQoutVsQsideVsQlongVsMtVsCentVsEventPlaneAngleVsQvector, o2::framework::HistType::kTHnSparseF, "hQoutVsQsideVsQlongVsMtVsCentVsEventPlaneAngleVsQvector", "Event shape enginering; q_{out} (GeV/#it{c}); q_{side} (GeV/#it{c}); q_{long} (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); centrality (%); #varphi_{pair} - #Psi_{EP}; q-vector;"},
367367
}};
368368

369369
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)

0 commit comments

Comments
 (0)