2424#include < tuple>
2525#include < utility>
2626
27+ #include " Math/Vector4D.h"
28+ #include " Math/Vector3D.h"
29+ #include " Math/LorentzRotation.h"
30+ #include " Math/Rotation3D.h"
31+ #include " Math/AxisAngle.h"
32+
2733#include " CCDB/BasicCCDBManager.h"
2834#include " Framework/AnalysisTask.h"
2935#include " Framework/ASoAHelpers.h"
3440#include " Common/Core/RecoDecay.h"
3541#include " Common/DataModel/Qvectors.h"
3642
43+ #include " DetectorsBase/GeometryManager.h"
44+ #include " DataFormatsEMCAL/Constants.h"
45+ #include " EMCALBase/Geometry.h"
46+ #include " EMCALCalib/BadChannelMap.h"
47+
3748#include " PWGEM/Dilepton/Utils/EMTrackUtilities.h"
3849#include " PWGEM/PhotonMeson/Core/EMCPhotonCut.h"
3950#include " PWGEM/PhotonMeson/Core/EMPhotonEventCut.h"
@@ -207,6 +218,9 @@ struct EMfTaskPi0Flow {
207218 fEMCCut .SetUseTM (emccuts.EMC_UseTM ); // disables TM
208219 o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms (®istry);
209220
221+ // Load EMCal geometry
222+ o2::emcal::Geometry::GetInstanceFromRunNumber (300000 );
223+
210224 const AxisSpec thnAxisInvMass{thnConfigAxisInvMass, " #it{M}_{#gamma#gamma} (GeV/#it{c}^{2})" };
211225 const AxisSpec thnAxisPt{thnConfigAxisPt, " #it{p}_{T} (GeV/#it{c})" };
212226 const AxisSpec thnAxisCent{thnConfigAxisCent, " Centrality (%)" };
@@ -223,7 +237,10 @@ struct EMfTaskPi0Flow {
223237 const AxisSpec thAxisPhi{72 , 0 , 2 * 3.14159 , " phi" };
224238 const AxisSpec thAxisNCell{17664 , 0.5 , +17664.5 , " #it{N}_{cell}" };
225239
240+ const AxisSpec thAxisPsi{360 / harmonic, 0 .f , 2 . / harmonic * M_PI, Form (" #Psi_{%d}" , harmonic.value )};
241+
226242 registry.add (" hSparsePi0Flow" , " THn for SP" , HistType::kTHnSparseF , {thnAxisInvMass, thnAxisPt, thnAxisCent, thnAxisScalarProd});
243+ registry.add (" hSparseBkgFlow" , " THn for SP" , HistType::kTHnSparseF , {thnAxisInvMass, thnAxisPt, thnAxisCent, thnAxisScalarProd});
227244 auto hClusterCuts = registry.add <TH1>(" hClusterCuts" , " hClusterCuts;;Counts" , kTH1D , {{6 , 0.5 , 6.5 }}, false );
228245 hClusterCuts->GetXaxis ()->SetBinLabel (1 , " in" );
229246 hClusterCuts->GetXaxis ()->SetBinLabel (2 , " opening angle" );
@@ -247,6 +264,9 @@ struct EMfTaskPi0Flow {
247264 }
248265
249266 if (saveEpResoHisto) {
267+ registry.add (" hEventPlaneAngleFT0M" , " hEventPlaneAngleFT0M" , HistType::kTH2D , {thnAxisCent, thAxisPsi});
268+ registry.add (" hEventPlaneAngleTPCpos" , " hEventPlaneAngleTPCpos" , HistType::kTH2D , {thnAxisCent, thAxisPsi});
269+ registry.add (" hEventPlaneAngleTPCneg" , " hEventPlaneAngleTPCneg" , HistType::kTH2D , {thnAxisCent, thAxisPsi});
250270 registry.add (" epReso/hEpResoFT0cFT0a" , " hEpResoFT0cFT0a; centrality; #Delta#Psi_{sub}" , {HistType::kTProfile , {thnAxisCent}});
251271 registry.add (" epReso/hEpResoFT0cTPCpos" , " hEpResoFT0cTPCpos; centrality; #Delta#Psi_{sub}" , {HistType::kTProfile , {thnAxisCent}});
252272 registry.add (" epReso/hEpResoFT0cTPCneg" , " hEpResoFT0cTPCneg; centrality; #Delta#Psi_{sub}" , {HistType::kTProfile , {thnAxisCent}});
@@ -454,6 +474,71 @@ struct EMfTaskPi0Flow {
454474 return isgood;
455475 }
456476
477+ // / \brief Calculate background using rotation background method
478+ template <typename TPhotons>
479+ void RotationBackground (const ROOT::Math::PtEtaPhiMVector& meson, ROOT::Math::PtEtaPhiMVector photon1, ROOT::Math::PtEtaPhiMVector photon2, TPhotons const & photons_coll, unsigned int ig1, unsigned int ig2, CollsWithQvecs::iterator const & collision)
480+ {
481+ // if less than 3 clusters are present skip event since we need at least 3 clusters
482+ if (photons_coll.size () < 3 ) {
483+ return ;
484+ }
485+
486+ auto [xQVec, yQVec] = getQvec (collision, qvecDetector);
487+ float cent = getCentrality (collision);
488+
489+ const float rotationAngle = M_PI / 2.0 ; // rotaion angle 90 degree
490+ ROOT::Math::AxisAngle rotationAxis (meson.Vect (), rotationAngle);
491+ ROOT::Math::Rotation3D rotationMatrix (rotationAxis);
492+ photon1 = rotationMatrix * photon1;
493+ photon2 = rotationMatrix * photon2;
494+
495+ for (auto & photon : photons_coll) {
496+ if (photon.globalIndex () == ig1 || photon.globalIndex () == ig2) {
497+ // only combine rotated photons with other photons
498+ continue ;
499+ }
500+ if (!(fEMCCut .IsSelected <EMCalPhotons::iterator>(photon))) {
501+ continue ;
502+ }
503+
504+ ROOT::Math::PtEtaPhiMVector photon3 (photon.pt (), photon.eta (), photon.phi (), 0 .);
505+ ROOT::Math::PtEtaPhiMVector mother1 = photon1 + photon3;
506+ ROOT::Math::PtEtaPhiMVector mother2 = photon2 + photon3;
507+
508+ float openingAngle1 = std::acos (photon1.Vect ().Dot (photon3.Vect ()) / (photon1.P () * photon3.P ()));
509+ float openingAngle2 = std::acos (photon2.Vect ().Dot (photon3.Vect ()) / (photon2.P () * photon3.P ()));
510+
511+ int iCellID_photon1 = 0 ;
512+ int iCellID_photon2 = 0 ;
513+
514+ float cosNPhi1 = std::cos (harmonic * mother1.Phi ());
515+ float sinNPhi1 = std::sin (harmonic * mother1.Phi ());
516+ float scalprodCand1 = cosNPhi1 * xQVec + sinNPhi1 * yQVec;
517+
518+ float cosNPhi2 = std::cos (harmonic * mother2.Phi ());
519+ float sinNPhi2 = std::sin (harmonic * mother2.Phi ());
520+ float scalprodCand2 = cosNPhi2 * xQVec + sinNPhi2 * yQVec;
521+
522+ try {
523+ iCellID_photon1 = o2::emcal::Geometry::GetInstance ()->GetAbsCellIdFromEtaPhi (photon1.Eta (), photon1.Phi ());
524+ } catch (o2::emcal::InvalidPositionException& e) {
525+ iCellID_photon1 = -1 ;
526+ }
527+ try {
528+ iCellID_photon2 = o2::emcal::Geometry::GetInstance ()->GetAbsCellIdFromEtaPhi (photon2.Eta (), photon2.Phi ());
529+ } catch (o2::emcal::InvalidPositionException& e) {
530+ iCellID_photon2 = -1 ;
531+ }
532+
533+ if (openingAngle1 > mesonConfig.minOpenAngle && iCellID_photon1 > 0 && thnConfigAxisInvMass.value [1 ] <= mother1.M () && thnConfigAxisInvMass.value .back () >= mother1.M () && thnConfigAxisPt.value [1 ] > mother1.Pt () && thnConfigAxisPt.value .back () < mother1.Pt ()) {
534+ registry.fill (HIST (" hSparseBkgFlow" ), mother1.M (), mother1.Pt (), cent, scalprodCand1);
535+ }
536+ if (openingAngle2 > mesonConfig.minOpenAngle && iCellID_photon2 > 0 && thnConfigAxisInvMass.value [1 ] <= mother2.M () && thnConfigAxisInvMass.value .back () >= mother2.M () && thnConfigAxisPt.value [1 ] > mother2.Pt () && thnConfigAxisPt.value .back () < mother2.Pt ()) {
537+ registry.fill (HIST (" hSparseBkgFlow" ), mother2.M (), mother2.Pt (), cent, scalprodCand2);
538+ }
539+ }
540+ }
541+
457542 // / Compute the scalar product
458543 // / \param collision is the collision with the Q vector information and event plane
459544 // / \param meson are the selected candidates
@@ -546,6 +631,8 @@ struct EMfTaskPi0Flow {
546631 ROOT::Math::PtEtaPhiMVector v2 (g2.pt (), g2.eta (), g2.phi (), 0 .);
547632 ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2;
548633
634+ RotationBackground<EMCalPhotons>(vMeson, v1, v2, photons_per_collision, g1.globalIndex (), g2.globalIndex (), collision);
635+
549636 float dTheta = v1.Theta () - v2.Theta ();
550637 float dPhi = v1.Phi () - v2.Phi ();
551638 float openingAngle = std::acos (v1.Vect ().Dot (v2.Vect ()) / (v1.P () * v2.P ()));
@@ -738,6 +825,10 @@ struct EMfTaskPi0Flow {
738825 float epBNegs = epHelper.GetEventPlane (xQVecBNeg, yQVecBNeg, harmonic);
739826 float epBTots = epHelper.GetEventPlane (xQVecBTot, yQVecBTot, harmonic);
740827
828+ registry.fill (HIST (" hEventPlaneAngleFT0M" ), centrality, epFT0m);
829+ registry.fill (HIST (" hEventPlaneAngleTPCpos" ), centrality, epBPoss);
830+ registry.fill (HIST (" hEventPlaneAngleTPCneg" ), centrality, epBNegs);
831+
741832 registry.fill (HIST (" epReso/hEpResoFT0cFT0a" ), centrality, std::cos (harmonic * getDeltaPsiInRange (epFT0c, epFT0a)));
742833 registry.fill (HIST (" epReso/hEpResoFT0cTPCpos" ), centrality, std::cos (harmonic * getDeltaPsiInRange (epFT0c, epBPoss)));
743834 registry.fill (HIST (" epReso/hEpResoFT0cTPCneg" ), centrality, std::cos (harmonic * getDeltaPsiInRange (epFT0c, epBNegs)));
0 commit comments