1616#ifndef PWGCF_FEMTODREAM_CORE_FEMTODREAMCOLLISIONSELECTION_H_
1717#define PWGCF_FEMTODREAM_CORE_FEMTODREAMCOLLISIONSELECTION_H_
1818
19- #include < string>
20- #include < iostream>
2119#include " Common/CCDB/TriggerAliases.h"
20+ #include " Common/Core/EventPlaneHelper.h"
2221#include " Common/DataModel/EventSelection.h"
22+ #include " Common/DataModel/Qvectors.h"
23+
2324#include " Framework/HistogramRegistry.h"
2425#include " Framework/Logger.h"
2526
27+ #include < iostream>
28+ #include < string>
29+ #include < vector>
30+
2631using namespace o2 ::framework;
2732
2833namespace o2 ::analysis::femtoDream
@@ -156,6 +161,36 @@ class FemtoDreamCollisionSelection
156161 return true ;
157162 }
158163
164+ // / Pile-up selection of PbPb collisions
165+ // / \tparam T type of the collision
166+ // / \param col Collision
167+ // / \return whether or not the collisions fulfills the specified selections
168+ template <typename C>
169+ bool isPileUpCollisionPbPb (C const & col,
170+ bool noSameBunchPileup, bool isGoodITSLayersAll)
171+ {
172+ if ((noSameBunchPileup && !col.selection_bit (aod::evsel::kNoSameBunchPileup )) || (isGoodITSLayersAll && !col.selection_bit (aod::evsel::kIsGoodITSLayersAll ))) {
173+ return false ;
174+ }
175+
176+ return true ;
177+ }
178+
179+ // / occupancy selection
180+ // / \tparam T type of the collision
181+ // / \param col Collision
182+ // / \return whether or not the collisions fulfills the specified selections
183+ template <typename C>
184+ bool occupancySelection (C const & col,
185+ int tpcOccupancyMin, int tpcOccupancyMax)
186+ {
187+ const auto occupancy = col.trackOccupancyInTimeRange ();
188+ if ((occupancy < tpcOccupancyMin || occupancy > tpcOccupancyMax)) {
189+ return false ;
190+ }
191+ return true ;
192+ }
193+
159194 // / Some basic QA of the event
160195 // / \tparam T type of the collision
161196 // / \param col Collision
@@ -175,6 +210,49 @@ class FemtoDreamCollisionSelection
175210 }
176211 }
177212
213+ // / Initializes histograms for qn bin
214+ // / \param registry Histogram registry to be passed
215+ void initQn (HistogramRegistry* registry, int mumQnBins = 10 )
216+ {
217+ mHistogramQn = registry;
218+ mHistogramQn ->add (" Event/centFT0CBefore" , " ; cent" , kTH1F , {{10 , 0 , 100 }});
219+ mHistogramQn ->add (" Event/centFT0CAfter" , " ; cent" , kTH1F , {{10 , 0 , 100 }});
220+ mHistogramQn ->add (" Event/centVsqn" , " ; cent; qn" , kTH2F , {{10 , 0 , 100 }, {100 , 0 , 1000 }});
221+ mHistogramQn ->add (" Event/centVsqnVsSpher" , " ; cent; qn; Sphericity" , kTH3F , {{10 , 0 , 100 }, {100 , 0 , 1000 }, {100 , 0 , 1 }});
222+ mHistogramQn ->add (" Event/qnBin" , " ; qnBin; entries" , kTH1F , {{20 , 0 , 20 }});
223+
224+ for (int iqn (0 ); iqn < mumQnBins; ++iqn) {
225+ qnMults.push_back (mHistogramQn ->add ((" Qn/mult_" + std::to_string (iqn)).c_str (), " ; cent; c22" , kTH1F , {{100 , 0 , 3500 }}));
226+ }
227+ return ;
228+ }
229+
230+ // / Initializes histograms for the flow calculation
231+ // / \param registry Histogram registry to be passed
232+ void initFlow (HistogramRegistry* registry, bool doQnSeparation, int mumQnBins = 10 , int binPt = 100 , int binEta = 32 )
233+ {
234+ if (!mCutsSet ) {
235+ LOGF (error, " Event selection not set - quitting!" );
236+ }
237+ mReQthisEvt = new TH2D (" ReQthisEvt" , " " , binPt, 0 ., 5 ., binEta, -0.8 , 0.8 );
238+ mImQthisEvt = new TH2D (" ImQthisEvt" , " " , binPt, 0 ., 5 ., binEta, -0.8 , 0.8 );
239+ mReQ2thisEvt = new TH2D (" ReQ2thisEvt" , " " , binPt, 0 ., 5 ., binEta, -0.8 , 0.8 );
240+ mImQ2thisEvt = new TH2D (" ImQ2thisEvt" , " " , binPt, 0 ., 5 ., binEta, -0.8 , 0.8 );
241+ mMQthisEvt = new TH2D (" MQthisEvt" , " " , binPt, 0 ., 5 ., binEta, -0.8 , 0.8 );
242+ mMQWeightthisEvt = new TH2D (" MQWeightthisEvt" , " " , binPt, 0 ., 5 ., binEta, -0.8 , 0.8 );
243+
244+ mHistogramQn = registry;
245+ mHistogramQn ->add <TProfile>(" Event/profileC22" , " ; cent; c22" , kTProfile , {{10 , 0 , 100 }});
246+ mHistogramQn ->add <TProfile>(" Event/profileC24" , " ; cent; c24" , kTProfile , {{10 , 0 , 100 }});
247+
248+ if (doQnSeparation) {
249+ for (int iqn (0 ); iqn < mumQnBins; ++iqn) {
250+ profilesC22.push_back (mHistogramQn ->add <TProfile>((" Qn/profileC22_" + std::to_string (iqn)).c_str (), " ; cent; c22" , kTProfile , {{10 , 0 , 100 }}));
251+ }
252+ }
253+ return ;
254+ }
255+
178256 // / \todo to be implemented!
179257 // / Compute the sphericity of an event
180258 // / Important here is that the filter on tracks does not interfere here!
@@ -246,6 +324,170 @@ class FemtoDreamCollisionSelection
246324 return spt;
247325 }
248326
327+ // / \todo to be implemented!
328+ // / Compute the qn-vector(FT0C) of an event
329+ // / \tparam T type of the collision
330+ // / \param col Collision
331+ // / \return value of the qn-vector of FT0C of the event
332+ template <typename T>
333+ float computeqnVec (T const & col)
334+ {
335+ double qn = std::sqrt (col.qvecFT0CReVec ()[0 ] * col.qvecFT0CReVec ()[0 ] + col.qvecFT0CImVec ()[0 ] * col.qvecFT0CImVec ()[0 ]) * std::sqrt (col.sumAmplFT0C ());
336+ return qn;
337+ }
338+
339+ // / \todo to be implemented!
340+ // / \return the 1-d qn-vector separator to 2-d
341+ std::vector<std::vector<float >> getQnBinSeparator2D (std::vector<float > flat, const int numQnBins = 10 )
342+ {
343+ size_t nBins = numQnBins + 1 ;
344+
345+ if (flat.empty () || flat.size () % nBins != 0 ) {
346+ LOGP (error, " ConfQnBinSeparator size = {} is not divisible by {}" ,
347+ flat.size (), nBins);
348+ return {{-999 , -999 }};
349+ }
350+
351+ size_t nCent = flat.size () / nBins;
352+ std::vector<std::vector<float >> res (nCent, std::vector<float >(nBins));
353+
354+ for (size_t i = 0 ; i < nCent; ++i) {
355+ for (size_t j = 0 ; j < nBins; ++j) {
356+ res[i][j] = flat[i * nBins + j];
357+ }
358+ }
359+ return res;
360+ }
361+
362+ // / \todo to be implemented!
363+ // / Get the bin number of qn-vector(FT0C) of an event
364+ // / \param centBinWidth centrality bin width, example: per 1%, per 10% ...
365+ // / \return bin number of qn-vector of the event
366+ int myqnBin (float centrality, float centMax, std::vector<float > qnBinSeparator, bool doFillHisto, float fSpher , float qn, const int numQnBins, float mult, float centBinWidth = 1 .f)
367+ {
368+ auto twoDSeparator = getQnBinSeparator2D (qnBinSeparator, numQnBins);
369+ if (twoDSeparator.empty () || twoDSeparator[0 ][0 ] == -999 .) {
370+ LOGP (warning, " ConfQnBinSeparator not set, using default fallback!" );
371+ return -999 ; // safe fallback
372+ }
373+
374+ if (doFillHisto)
375+ mHistogramQn ->fill (HIST (" Event/centFT0CBefore" ), centrality);
376+
377+ int qnBin = -999 ;
378+ int mycentBin = static_cast <int >(centrality / centBinWidth);
379+ if (mycentBin >= static_cast <int >(centMax / centBinWidth))
380+ return qnBin;
381+
382+ if (mycentBin > static_cast <int >(twoDSeparator.size ()) - 1 )
383+ return qnBin;
384+
385+ for (int iqn (0 ); iqn < static_cast <int >(twoDSeparator[mycentBin].size ()) - 1 ; ++iqn) {
386+ if (qn > twoDSeparator[mycentBin][iqn] && qn <= twoDSeparator[mycentBin][iqn + 1 ]) {
387+ qnBin = iqn;
388+ break ;
389+ } else {
390+ continue ;
391+ }
392+ }
393+
394+ mQnBin = qnBin;
395+
396+ if (doFillHisto) {
397+ mHistogramQn ->fill (HIST (" Event/centFT0CAfter" ), centrality);
398+ mHistogramQn ->fill (HIST (" Event/centVsqn" ), centrality, qn);
399+ mHistogramQn ->fill (HIST (" Event/centVsqnVsSpher" ), centrality, qn, fSpher );
400+ mHistogramQn ->fill (HIST (" Event/qnBin" ), qnBin);
401+ if (qnBin >= 0 && qnBin < numQnBins) {
402+ std::get<std::shared_ptr<TH1>>(qnMults[qnBin])->Fill (mult);
403+ }
404+ }
405+
406+ return qnBin;
407+ }
408+
409+ // / \todo to be implemented!
410+ // / Fill cumulants histo for flow calculation
411+ // / Reset hists event-by-event
412+ // / \tparam T1 type of the collision
413+ // / \tparam T2 type of the tracks
414+ // / \param tracks All tracks
415+ template <typename T1, typename T2>
416+ bool fillCumulants (T1 const & col, T2 const & tracks, float fHarmonic = 2 .f)
417+ {
418+ int numOfTracks = col.numContrib ();
419+ if (numOfTracks < 3 )
420+ return false ;
421+
422+ mReQthisEvt ->Reset ();
423+ mImQthisEvt ->Reset ();
424+ mReQ2thisEvt ->Reset ();
425+ mImQ2thisEvt ->Reset ();
426+ mMQthisEvt ->Reset ();
427+ mMQWeightthisEvt ->Reset ();
428+
429+ for (auto const & track : tracks) {
430+ double weight = 1 ; // Will implement NUA&NUE correction
431+ double phi = track.phi ();
432+ double pt = track.pt ();
433+ double eta = track.eta ();
434+ double cosnphi = weight * TMath::Cos (fHarmonic * phi);
435+ double sinnphi = weight * TMath::Sin (fHarmonic * phi);
436+ double cos2nphi = weight * TMath::Cos (2 * fHarmonic * phi);
437+ double sin2nphi = weight * TMath::Sin (2 * fHarmonic * phi);
438+ mReQthisEvt ->Fill (pt, eta, cosnphi);
439+ mImQthisEvt ->Fill (pt, eta, sinnphi);
440+ mReQ2thisEvt ->Fill (pt, eta, cos2nphi);
441+ mImQ2thisEvt ->Fill (pt, eta, sin2nphi);
442+ mMQthisEvt ->Fill (pt, eta);
443+ mMQWeightthisEvt ->Fill (pt, eta, weight);
444+ }
445+ return true ;
446+ }
447+
448+ // / \todo to be implemented!
449+ // / Do cumulants for flow calculation
450+ // / \tparam T type of the collision
451+ // / \param doQnSeparation to fill flow in divied qn bins
452+ // / \param qnBin should be <int> in 0-9
453+ // / \param fEtaGap eta gap for flow cumulant
454+ template <typename T1, typename T2>
455+ void doCumulants (T1 const & col, T2 const & tracks, float centrality, bool doQnSeparation = false , int numQnBins = 10 , float fEtaGap = 0 .3f , int binPt = 100 , int binEta = 32 )
456+ {
457+ if (!fillCumulants (col, tracks))
458+ return ;
459+
460+ if (mMQthisEvt ->Integral (1 , binPt, 1 , binEta) < 2 )
461+ return ;
462+
463+ double allReQ = mReQthisEvt ->Integral (1 , binPt, 1 , binEta);
464+ double allImQ = mImQthisEvt ->Integral (1 , binPt, 1 , binEta);
465+ TComplex Q (allReQ, allImQ);
466+ TComplex QStar = TComplex::Conjugate (Q);
467+
468+ double posEtaRe = mReQthisEvt ->Integral (1 , binPt, mReQthisEvt ->GetYaxis ()->FindBin (fEtaGap + 1e-6 ), binEta);
469+ double posEtaIm = mImQthisEvt ->Integral (1 , binPt, mImQthisEvt ->GetYaxis ()->FindBin (fEtaGap + 1e-6 ), binEta);
470+ if (mMQthisEvt ->Integral (1 , binPt, mMQthisEvt ->GetYaxis ()->FindBin (fEtaGap + 1e-6 ), binEta) < 2 )
471+ return ;
472+ float posEtaMQ = mMQWeightthisEvt ->Integral (1 , binPt, mMQthisEvt ->GetYaxis ()->FindBin (fEtaGap + 1e-6 ), binEta);
473+ TComplex posEtaQ = TComplex (posEtaRe, posEtaIm);
474+ TComplex posEtaQStar = TComplex::Conjugate (posEtaQ);
475+
476+ double negEtaRe = mReQthisEvt ->Integral (1 , binPt, 1 , mReQthisEvt ->GetYaxis ()->FindBin (-1 * fEtaGap - 1e-6 ));
477+ double negEtaIm = mImQthisEvt ->Integral (1 , binPt, 1 , mImQthisEvt ->GetYaxis ()->FindBin (-1 * fEtaGap - 1e-6 ));
478+ if (mMQthisEvt ->Integral (1 , binPt, 1 , mMQthisEvt ->GetYaxis ()->FindBin (-1 * fEtaGap - 1e-6 )) < 2 )
479+ return ;
480+ float negEtaMQ = mMQWeightthisEvt ->Integral (1 , binPt, 1 , mMQthisEvt ->GetYaxis ()->FindBin (-1 * fEtaGap - 1e-6 ));
481+ TComplex negEtaQ = TComplex (negEtaRe, negEtaIm);
482+ TComplex negEtaQStar = TComplex::Conjugate (negEtaQ);
483+
484+ mHistogramQn ->get <TProfile>(HIST (" Event/profileC22" ))->Fill (centrality, (negEtaQ * posEtaQStar).Re () / (negEtaMQ * posEtaMQ), (negEtaMQ * posEtaMQ));
485+ if (doQnSeparation && mQnBin >= 0 && mQnBin < numQnBins) {
486+ std::get<std::shared_ptr<TProfile>>(profilesC22[mQnBin ])->Fill (centrality, (negEtaQ * posEtaQStar).Re () / (negEtaMQ * posEtaMQ), (negEtaMQ * posEtaMQ));
487+ }
488+ return ;
489+ }
490+
249491 private:
250492 HistogramRegistry* mHistogramRegistry = nullptr ; // /< For QA output
251493 bool mCutsSet = false ; // /< Protection against running without cuts
@@ -257,6 +499,16 @@ class FemtoDreamCollisionSelection
257499 float mZvtxMax = 999 .f; // /< Maximal deviation from nominal z-vertex (cm)
258500 float mMinSphericity = 0 .f;
259501 float mSphericityPtmin = 0 .f;
502+ int mQnBin = -999 ;
503+ HistogramRegistry* mHistogramQn = nullptr ; // /< For flow cumulant output
504+ std::vector<HistPtr> qnMults; // / Histograms of multiplicity (TH1F) per Qn bin. Stored as HistPtr (variant of shared_ptr) from HistogramManager.
505+ std::vector<HistPtr> profilesC22; // / Pofile Histograms of c22 per Qn bin
506+ TH2D* mReQthisEvt = nullptr ; // /< For flow cumulant in an event
507+ TH2D* mImQthisEvt = nullptr ; // /< For flow cumulant in an event
508+ TH2D* mReQ2thisEvt = nullptr ; // /< For flow cumulant in an event
509+ TH2D* mImQ2thisEvt = nullptr ; // /< For flow cumulant in an event
510+ TH2D* mMQthisEvt = nullptr ; // /< For flow cumulant in an event
511+ TH2D* mMQWeightthisEvt = nullptr ; // /< For flow cumulant in an event
260512};
261513} // namespace o2::analysis::femtoDream
262514
0 commit comments