3030
3131#include < TMath.h>
3232
33+ #include < cmath>
3334#include < string>
3435#include < string_view>
3536#include < utility>
@@ -221,9 +222,14 @@ class FemtoDreamContainer
221222 // / Initialize the histograms for pairs with 3D component in divided qn bins
222223 template <typename T>
223224 void init_base_3Dqn (const std::string& folderName, const std::string& femtoDKout, const std::string& femtoDKside, const std::string& femtoDKlong,
224- T& femtoDKoutAxis, T& femtoDKsideAxis, T& femtoDKlongAxis, T& mTAxi4D , T& multPercentileAxis4D, T& qnAxis, T& pairPhiAxis)
225+ T& femtoDKoutAxis, T& femtoDKsideAxis, T& femtoDKlongAxis, T& mTAxi4D , T& multPercentileAxis4D, T& qnAxis, T& pairPhiAxis, bool storeEProt )
225226 {
226- mHistogramRegistry ->add ((folderName + " /relPair3dRmTMultPercentileQnPairphi" ).c_str (), (" ; " + femtoDKout + femtoDKside + femtoDKlong + " ; #it{m}_{T} (GeV/#it{c}); Centrality; qn; #varphi_{pair} - #Psi_{EP}" ).c_str (), o2::framework::HistType::kTHnSparseF , {femtoDKoutAxis, femtoDKsideAxis, femtoDKlongAxis, mTAxi4D , multPercentileAxis4D, qnAxis, pairPhiAxis});
227+ if (storeEProt) {
228+ // DK_x, DK_y, DK_z are the EP-rotated (B-frame) axes; DK_y is out-of-plane (||B).
229+ mHistogramRegistry ->add ((folderName + " /relPair3dEProtRmTMultPercentileQnPairphi" ).c_str (), " ; DK_{x} (GeV/#it{c}); DK_{y} (GeV/#it{c}); DK_{z} (GeV/#it{c}); #it{m}_{T} (GeV/#it{c}); Centrality; qn; #varphi_{pair} - #Psi_{EP}" , o2::framework::HistType::kTHnSparseF , {femtoDKoutAxis, femtoDKsideAxis, femtoDKlongAxis, mTAxi4D , multPercentileAxis4D, qnAxis, pairPhiAxis});
230+ } else {
231+ mHistogramRegistry ->add ((folderName + " /relPair3dRmTMultPercentileQnPairphi" ).c_str (), (" ; " + femtoDKout + femtoDKside + femtoDKlong + " ; #it{m}_{T} (GeV/#it{c}); Centrality; qn; #varphi_{pair} - #Psi_{EP}" ).c_str (), o2::framework::HistType::kTHnSparseF , {femtoDKoutAxis, femtoDKsideAxis, femtoDKlongAxis, mTAxi4D , multPercentileAxis4D, qnAxis, pairPhiAxis});
232+ }
227233 }
228234
229235 template <typename T>
@@ -261,15 +267,23 @@ class FemtoDreamContainer
261267 framework::AxisSpec qnAxis = {std::move (qnBins), " qn" };
262268 framework::AxisSpec pairPhiAxis = {std::move (pairPhiBins), " #varphi_{pair} - #Psi_{EP} (rad)" };
263269
270+ // EP-rotated (B-frame) axis labels, same binning as out/side/long.
271+ framework::AxisSpec DKxAxis = {DKoutBins, " DK_{x} (GeV/#it{c})" };
272+ framework::AxisSpec DKyAxis = {DKsideBins, " DK_{y} (GeV/#it{c})" };
273+ framework::AxisSpec DKzAxis = {DKlongBins, " DK_{z} (GeV/#it{c})" };
274+ framework::AxisSpec& mom1Axis = mStoreEProt ? DKxAxis : DKoutAxis;
275+ framework::AxisSpec& mom2Axis = mStoreEProt ? DKyAxis : DKsideAxis;
276+ framework::AxisSpec& mom3Axis = mStoreEProt ? DKzAxis : DKlongAxis;
277+
264278 std::string folderName = static_cast <std::string>(mFolderSuffix [mEventType ]) + static_cast <std::string>(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kRecon ]) + static_cast <std::string>(" _3Dqn" );
265279
266280 init_base_3Dqn (folderName, femtoObsDKout, femtoObsDKside, femtoObsDKlong,
267- DKoutAxis, DKsideAxis, DKlongAxis , mTAxis4D , multPercentileAxis4D, qnAxis, pairPhiAxis);
281+ mom1Axis, mom2Axis, mom3Axis , mTAxis4D , multPercentileAxis4D, qnAxis, pairPhiAxis, mStoreEProt );
268282
269283 if (isMC) {
270284 folderName = static_cast <std::string>(mFolderSuffix [mEventType ]) + static_cast <std::string>(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth ]) + static_cast <std::string>(" _3Dqn" );
271285 init_base_3Dqn (folderName, femtoObsDKout, femtoObsDKside, femtoObsDKlong,
272- DKoutAxis, DKsideAxis, DKlongAxis , mTAxis4D , multPercentileAxis4D, qnAxis, pairPhiAxis);
286+ mom1Axis, mom2Axis, mom3Axis , mTAxis4D , multPercentileAxis4D, qnAxis, pairPhiAxis, mStoreEProt );
273287 init_3Dqn_MC (folderName, femtoObsDKout, femtoObsDKside, femtoObsDKlong,
274288 DKoutAxis, DKsideAxis, DKlongAxis, smearingByOrigin);
275289 }
@@ -286,6 +300,9 @@ class FemtoDreamContainer
286300 mPDGTwo = pdg2;
287301 }
288302
303+ // / Store EP-rotated (B-frame) DK_x,DK_y,DK_z instead of out,side,long. Call before init_3Dqn().
304+ void setStoreEProt (bool doStore) { mStoreEProt = doStore; }
305+
289306 // / Pass a pair to the container and compute all the relevant observables
290307 // / Called by setPair both in case of data/ and Monte Carlo reconstructed and for Monte Carlo truth
291308 // / \tparam T type of the femtodreamparticle
@@ -501,11 +518,42 @@ class FemtoDreamContainer
501518 }
502519 }
503520
521+ // / Signed φ_pair − Ψ_EP (same as FemtoDreamMath::getPairPhiEP but without the final |·|); used as the B-frame rotation angle.
522+ template <typename T1 , typename T2 >
523+ static float getPairPhiEPSigned (const T1 & part1, const float mass1, const T2 & part2, const float mass2, const float Psi_ep)
524+ {
525+ const ROOT ::Math::PtEtaPhiMVector vecpart1 (part1.pt (), part1.eta (), part1.phi (), mass1);
526+ const ROOT ::Math::PtEtaPhiMVector vecpart2 (part2.pt (), part2.eta (), part2.phi (), mass2);
527+ const ROOT ::Math::PtEtaPhiMVector trackSum = vecpart1 + vecpart2;
528+ return TVector2::Phi_mpi_pi (trackSum.Phi () - Psi_ep);
529+ }
530+
531+ // / Signed counterpart of the plane-calibrated (two-event-plane) FemtoDreamMath::getPairPhiEP.
532+ template <typename T1 , typename T2 >
533+ static float getPairPhiEPSigned (const T1 & part1, const float mass1, const T2 & part2, const float mass2, const float Psi_ep1, const float Psi_ep2)
534+ {
535+ const ROOT ::Math::PtEtaPhiMVector vecpart1 (part1.pt (), part1.eta (), part1.phi (), mass1);
536+ const ROOT ::Math::PtEtaPhiMVector vecpart2 (part2.pt (), part2.eta (), part2.phi (), mass2);
537+ const float psidiff = Psi_ep2 - Psi_ep1;
538+ const float newPhi2 = TVector2::Phi_mpi_pi (vecpart2.Phi () - psidiff);
539+ const ROOT ::Math::PtEtaPhiMVector vecpart2_calibd (vecpart2.Pt (), vecpart2.Eta (), newPhi2, vecpart2.M ());
540+ const ROOT ::Math::PtEtaPhiMVector trackSum = vecpart1 + vecpart2_calibd;
541+ return TVector2::Phi_mpi_pi (trackSum.Phi () - Psi_ep1);
542+ }
543+
504544 // / Pass a pair to the container and compute all the relevant observables in divided qn bins
505545 template <o2::aod::femtodreamMCparticle::MCType mc>
506- void setPair_3Dqn_base (const float femtoDKout, const float femtoDKside, const float femtoDKlong, const float mT , const float multPercentile, const float myQnBin, const float pairPhiEP)
546+ void setPair_3Dqn_base (const float femtoDKout, const float femtoDKside, const float femtoDKlong, const float mT , const float multPercentile, const float myQnBin, const float pairPhiEP, bool storeEProt, const float pairPhiEPforRot )
507547 {
508- mHistogramRegistry ->fill (HIST (mFolderSuffix [mEventType ]) + HIST (o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST (" _3Dqn" ) + HIST (" /relPair3dRmTMultPercentileQnPairphi" ), femtoDKout, femtoDKside, femtoDKlong, mT , multPercentile, myQnBin, pairPhiEP);
548+ if (storeEProt) {
549+ // Rotate (out, side) by the signed φ_pair − Ψ_EP so DK_y is out-of-plane (||B); DK_z unchanged.
550+ const float DKx = femtoDKout * std::cos (pairPhiEPforRot) - femtoDKside * std::sin (pairPhiEPforRot);
551+ const float DKy = femtoDKout * std::sin (pairPhiEPforRot) + femtoDKside * std::cos (pairPhiEPforRot);
552+ const float DKz = femtoDKlong;
553+ mHistogramRegistry ->fill (HIST (mFolderSuffix [mEventType ]) + HIST (o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST (" _3Dqn" ) + HIST (" /relPair3dEProtRmTMultPercentileQnPairphi" ), DKx, DKy, DKz, mT , multPercentile, myQnBin, pairPhiEP);
554+ } else {
555+ mHistogramRegistry ->fill (HIST (mFolderSuffix [mEventType ]) + HIST (o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST (" _3Dqn" ) + HIST (" /relPair3dRmTMultPercentileQnPairphi" ), femtoDKout, femtoDKside, femtoDKlong, mT , multPercentile, myQnBin, pairPhiEP);
556+ }
509557 }
510558
511559 // / Called by setPair_3Dqn only in case of Monte Carlo truth
@@ -535,9 +583,10 @@ class FemtoDreamContainer
535583 const float mT = FemtoDreamMath::getmT (part1, mMassOne , part2, mMassTwo );
536584
537585 const float pairPhiEP = FemtoDreamMath::getPairPhiEP (part1, mMassOne , part2, mMassTwo , eventPlane);
586+ const float pairPhiEPforRot = mStoreEProt ? getPairPhiEPSigned (part1, mMassOne , part2, mMassTwo , eventPlane) : 0 .f ;
538587
539588 if (mHistogramRegistry ) {
540- setPair_3Dqn_base<o2::aod::femtodreamMCparticle::MCType::kRecon >(DKout, DKside, DKlong, mT , multPercentile, myQnBin, pairPhiEP);
589+ setPair_3Dqn_base<o2::aod::femtodreamMCparticle::MCType::kRecon >(DKout, DKside, DKlong, mT , multPercentile, myQnBin, pairPhiEP, mStoreEProt , pairPhiEPforRot );
541590
542591 if constexpr (isMC) {
543592 if (part1.has_fdMCParticle () && part2.has_fdMCParticle ()) {
@@ -549,9 +598,10 @@ class FemtoDreamContainer
549598 }
550599 const float mTMC = FemtoDreamMath::getmT (part1.fdMCParticle (), mMassOne , part2.fdMCParticle (), mMassTwo );
551600 const float pairPhiEPMC = FemtoDreamMath::getPairPhiEP (part1.fdMCParticle (), mMassOne , part2.fdMCParticle (), mMassTwo , eventPlane);
601+ const float pairPhiEPMCforRot = mStoreEProt ? getPairPhiEPSigned (part1.fdMCParticle (), mMassOne , part2.fdMCParticle (), mMassTwo , eventPlane) : 0 .f ;
552602
553603 if (std::abs (part1.fdMCParticle ().pdgMCTruth ()) == mPDGOne && std::abs (part2.fdMCParticle ().pdgMCTruth ()) == mPDGTwo ) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates
554- setPair_3Dqn_base<o2::aod::femtodreamMCparticle::MCType::kTruth >(k3dMC[1 ], k3dMC[2 ], k3dMC[3 ], mTMC , multPercentile, myQnBin, pairPhiEPMC);
604+ setPair_3Dqn_base<o2::aod::femtodreamMCparticle::MCType::kTruth >(k3dMC[1 ], k3dMC[2 ], k3dMC[3 ], mTMC , multPercentile, myQnBin, pairPhiEPMC, mStoreEProt , pairPhiEPMCforRot );
555605 setPair_3Dqn_MC (k3dMC, k3d, part1.fdMCParticle ().partOriginMCTruth (), part2.fdMCParticle ().partOriginMCTruth (), smearingByOrigin);
556606 } else {
557607 mHistogramRegistry ->fill (HIST (mFolderSuffix [mEventType ]) + HIST (o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth ]) + HIST (" /hFakePairsCounter" ), 0 );
@@ -580,9 +630,10 @@ class FemtoDreamContainer
580630 const float mT = FemtoDreamMath::getmT (part1, mMassOne , part2, mMassTwo );
581631
582632 const float pairPhiEP = FemtoDreamMath::getPairPhiEP (part1, mMassOne , part2, mMassTwo , EP1 , EP2 );
633+ const float pairPhiEPforRot = mStoreEProt ? getPairPhiEPSigned (part1, mMassOne , part2, mMassTwo , EP1 , EP2 ) : 0 .f ;
583634
584635 if (mHistogramRegistry ) {
585- setPair_3Dqn_base<o2::aod::femtodreamMCparticle::MCType::kRecon >(DKout, DKside, DKlong, mT , multPercentile, myQnBin, pairPhiEP);
636+ setPair_3Dqn_base<o2::aod::femtodreamMCparticle::MCType::kRecon >(DKout, DKside, DKlong, mT , multPercentile, myQnBin, pairPhiEP, mStoreEProt , pairPhiEPforRot );
586637
587638 if constexpr (isMC) {
588639 if (part1.has_fdMCParticle () && part2.has_fdMCParticle ()) {
@@ -594,9 +645,10 @@ class FemtoDreamContainer
594645 }
595646 const float mTMC = FemtoDreamMath::getmT (part1.fdMCParticle (), mMassOne , part2.fdMCParticle (), mMassTwo );
596647 const float pairPhiEPMC = FemtoDreamMath::getPairPhiEP (part1.fdMCParticle (), mMassOne , part2.fdMCParticle (), mMassTwo , EP1 , EP2 );
648+ const float pairPhiEPMCforRot = mStoreEProt ? getPairPhiEPSigned (part1.fdMCParticle (), mMassOne , part2.fdMCParticle (), mMassTwo , EP1 , EP2 ) : 0 .f ;
597649
598650 if (std::abs (part1.fdMCParticle ().pdgMCTruth ()) == mPDGOne && std::abs (part2.fdMCParticle ().pdgMCTruth ()) == mPDGTwo ) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates
599- setPair_3Dqn_base<o2::aod::femtodreamMCparticle::MCType::kTruth >(k3dMC[1 ], k3dMC[2 ], k3dMC[3 ], mTMC , multPercentile, myQnBin, pairPhiEPMC);
651+ setPair_3Dqn_base<o2::aod::femtodreamMCparticle::MCType::kTruth >(k3dMC[1 ], k3dMC[2 ], k3dMC[3 ], mTMC , multPercentile, myQnBin, pairPhiEPMC, mStoreEProt , pairPhiEPMCforRot );
600652 setPair_3Dqn_MC (k3dMC, k3d, part1.fdMCParticle ().partOriginMCTruth (), part2.fdMCParticle ().partOriginMCTruth (), smearingByOrigin);
601653 } else {
602654 mHistogramRegistry ->fill (HIST (mFolderSuffix [mEventType ]) + HIST (o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth ]) + HIST (" /hFakePairsCounter" ), 0 );
@@ -619,6 +671,7 @@ class FemtoDreamContainer
619671 int mPDGOne = 0 ; // /< PDG code of particle 1
620672 int mPDGTwo = 0 ; // /< PDG code of particle 2
621673 float mHighkstarCut = 6 .;
674+ bool mStoreEProt = false ; // /< Store EP-rotated (B-frame) DK_x,DK_y,DK_z instead of out,side,long
622675};
623676
624677} // namespace o2::analysis::femtoDream
0 commit comments