@@ -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
0 commit comments