Skip to content

Commit 8231bb2

Browse files
committed
Fix: fix event plane angle and q-vector calculation
1 parent 824bb1e commit 8231bb2

3 files changed

Lines changed: 60 additions & 29 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/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: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#ifndef PWGCF_FEMTO_CORE_MODES_H_
1717
#define PWGCF_FEMTO_CORE_MODES_H_
1818

19+
#include "dataTypes.h"
1920
#include "PWGCF/Femto/Core/dataTypes.h"
2021

2122
#include <cstdint>
@@ -178,10 +179,10 @@ enum class CharmHadron : o2::analysis::femto::datatypes::CharmHadronType {
178179
kLcBar
179180
};
180181

181-
enum class QvecDetector : o2::analysis::femto::datatypes::QvecDetectorType {
182+
enum class EventShapeDetector : o2::analysis::femto::datatypes::EventShapeDetectorType {
182183
kFT0C = 0,
183184
kFT0A = 1,
184-
kQvecDetectorLast = 2
185+
kEventShapeDetectorLast = 2
185186
};
186187

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

0 commit comments

Comments
 (0)