diff --git a/PWGEM/PhotonMeson/Core/EMCPhotonCut.h b/PWGEM/PhotonMeson/Core/EMCPhotonCut.h index aa42565e5ea..95ca402c913 100644 --- a/PWGEM/PhotonMeson/Core/EMCPhotonCut.h +++ b/PWGEM/PhotonMeson/Core/EMCPhotonCut.h @@ -41,6 +41,20 @@ static constexpr bool HasPrimaries = !std::is_same_v template static constexpr bool HasSecondaries = !std::is_same_v; +template +concept IsNonLinIterator = o2::soa::is_iterator && requires(T t) { + // Check that the *elements* of the container have the required methods: + { t.corrE() } -> std::same_as; + { t.corrPt() } -> std::same_as; +}; + +template +concept IsNonLinContainer = o2::soa::is_table && requires(T t) { + // Check that the *elements* of the container have the required methods: + { t.begin().corrE() } -> std::same_as; + { t.begin().corrPt() } -> std::same_as; +}; + template concept IsTrackIterator = o2::soa::is_iterator && requires(T t) { // Check that the *elements* of the container have the required methods: @@ -114,7 +128,7 @@ class EMCPhotonCut : public TNamed static const char* mCutNames[static_cast(EMCPhotonCuts::kNCuts)]; - constexpr auto getClusterId(o2::soa::is_iterator auto const& t) const + static constexpr auto getClusterId(o2::soa::is_iterator auto const& t) { if constexpr (requires { t.emEmcClusterId(); }) { return t.emEmcClusterId(); @@ -384,7 +398,11 @@ class EMCPhotonCut : public TNamed return cluster.definition() == mDefinition; case EMCPhotonCuts::kEnergy: - return cluster.e() > mMinE; + if constexpr (IsNonLinIterator>) { + return cluster.corrE() > mMinE; + } else { + return cluster.e() > mMinE; + } case EMCPhotonCuts::kNCell: return cluster.nCells() >= mMinNCell; @@ -478,7 +496,11 @@ class EMCPhotonCut : public TNamed return cluster.definition() == mDefinition; case EMCPhotonCuts::kEnergy: - return cluster.e() > mMinE; + if constexpr (IsNonLinIterator) { + return cluster.corrE() > mMinE; + } else { + return cluster.e() > mMinE; + } case EMCPhotonCuts::kNCell: return cluster.nCells() >= mMinNCell; @@ -496,7 +518,9 @@ class EMCPhotonCut : public TNamed auto dPhi = std::fabs(emcmatchedtrack.deltaPhi()); auto trackpt = emcmatchedtrack.trackPt(); auto trackp = emcmatchedtrack.trackP(); - bool result = (dEta > GetTrackMatchingEta(trackpt)) || (dPhi > GetTrackMatchingPhi(trackpt)) || (cluster.e() / trackp >= mMinEoverP); + bool result = (dEta > GetTrackMatchingEta(trackpt)) || + (dPhi > GetTrackMatchingPhi(trackpt)) || + (cluster.e() / trackp >= mMinEoverP); if (!result) { return false; } @@ -506,7 +530,7 @@ class EMCPhotonCut : public TNamed auto dPhis = cluster.deltaPhi(); // std:vector auto trackspt = cluster.trackpt(); // std:vector auto tracksp = cluster.trackp(); // std:vector - int ntrack = tracksp.size(); + int ntrack = trackspt.size(); for (int itr = 0; itr < ntrack; itr++) { float dEta = std::fabs(dEtas[itr]); float dPhi = std::fabs(dPhis[itr]); @@ -526,8 +550,8 @@ class EMCPhotonCut : public TNamed auto dEta = std::fabs(emcmatchedtrack.deltaEta()); auto dPhi = std::fabs(emcmatchedtrack.deltaPhi()); auto trackpt = emcmatchedtrack.trackPt(); - auto trackp = emcmatchedtrack.trackP(); - bool result = (dEta > GetSecTrackMatchingEta(trackpt)) || (dPhi > GetSecTrackMatchingPhi(trackpt)) || (cluster.e() / trackp >= mMinEoverP); + bool result = (dEta > GetSecTrackMatchingEta(trackpt)) || + (dPhi > GetSecTrackMatchingPhi(trackpt)); if (!result) { return false; } @@ -536,8 +560,7 @@ class EMCPhotonCut : public TNamed auto dEtas = cluster.deltaEtaSec(); // std:vector auto dPhis = cluster.deltaPhiSec(); // std:vector auto trackspt = cluster.trackptSec(); // std:vector - auto tracksp = cluster.trackpSec(); // std:vector - int ntrack = tracksp.size(); + int ntrack = trackspt.size(); for (int itr = 0; itr < ntrack; itr++) { float dEta = std::fabs(dEtas[itr]); float dPhi = std::fabs(dPhis[itr]); diff --git a/PWGEM/PhotonMeson/Core/EMNonLin.cxx b/PWGEM/PhotonMeson/Core/EMNonLin.cxx index db083d6bcee..bb5102dfc2a 100644 --- a/PWGEM/PhotonMeson/Core/EMNonLin.cxx +++ b/PWGEM/PhotonMeson/Core/EMNonLin.cxx @@ -15,43 +15,52 @@ #include "EMNonLin.h" -#include +#include using namespace o2::pwgem::nonlin; -float EMNonLin::getCorrectionFactor(float inputCalibValue, PhotonType photonType, float cent) +float EMNonLin::getCorrectionFactor(float x, const Context& ctx) { - float param0 = 0, param1 = 0, param2 = 0, val = 1.f; - switch (photonType) { - case PhotonType::kEMC: - if (cent >= 30 && cent <= 40) { - param0 = -5.33426e-01f; - param1 = 1.40144e-02f; - param2 = -5.24434e-01f; - } else { - param0 = 0.f; - param1 = 0.f; - param2 = 0.f; - } - break; - case PhotonType::kPCM: - if (cent >= 0 && cent <= 100) { - param0 = 10.7203f; - param1 = 0.0383968f; - param2 = 10.6025f; - } else { - param0 = 0.f; - param1 = 0.f; - param2 = 0.f; - } - break; - case PhotonType::kPHOS: - param0 = 0.f; - param1 = 0.f; - param2 = 0.f; + if (!ctx.params || x == 0.f) [[unlikely]] { + return x; + } + + float val = x; + // safety measure + int maxIter = std::min(ctx.nIter, MaxIter - 1); + + for (int i = 0; i <= maxIter; ++i) { + if (val == 0.f) { break; + } + + float inv = 1.f / val; + val *= (1.f + ctx.params[i].par0 * inv + + ctx.params[i].par1 * inv * inv) / + (1.f + ctx.params[i].par2 * inv); } - val = (1.f + param0 / inputCalibValue + param1 / std::pow(inputCalibValue, 2.f)) / (1.f + param2 / inputCalibValue); return val; } + +const EMNonLin::NonLinParams* EMNonLin::resolveParams(PhotonType type, float cent) +{ + int centBin = static_cast(cent / 10.f); + if (centBin < 0) + centBin = 0; + if (centBin >= CentBins) + centBin = CentBins - 1; + + return &kNonLinTable[static_cast(type)][centBin][0]; +} + +const EMNonLin::NonLinParams* EMNonLin::resolveParamsMC(PhotonType type, float cent) +{ + int centBin = static_cast(cent / 10.f); + if (centBin < 0) + centBin = 0; + if (centBin >= CentBins) + centBin = CentBins - 1; + + return &kNonLinTableMC[static_cast(type)][centBin][0]; +} diff --git a/PWGEM/PhotonMeson/Core/EMNonLin.h b/PWGEM/PhotonMeson/Core/EMNonLin.h index 44112e4221a..e9bce15c260 100644 --- a/PWGEM/PhotonMeson/Core/EMNonLin.h +++ b/PWGEM/PhotonMeson/Core/EMNonLin.h @@ -24,28 +24,283 @@ namespace o2::pwgem::nonlin { /// \class EMNonLin -/// \brief Dynamically-sized bit container with bit-level storage. -/// -/// Bits can be set beyond the current size, in which case the container -/// grows automatically. Access via test() and reset() requires the index -/// to be within the current size. Bits are all on by default and will be -/// switched off if particle fails a cut +/// \brief Class to obtain non linear correction factors for PbPb. class EMNonLin { public: + static constexpr int MaxIter = 2; + static constexpr int PhotonN = 3; + static constexpr int CentBins = 10; + enum class PhotonType : uint8_t { kEMC = 0, kPCM = 1, kPHOS = 2 // just in case }; - /// \brief gets the correction value for energy or pT for a specicif + struct NonLinParams { + float par0{0.f}; + float par1{0.f}; + float par2{0.f}; + }; + + struct Context { + const NonLinParams* params = nullptr; + int nIter = 0; + + void setParams(const NonLinParams* newParams) + { + params = newParams; + } + + void setIter(int iter) + { + if (iter < 0 || iter >= MaxIter) { + nIter = MaxIter - 1; + return; + } + + nIter = iter; + } + }; + + /// \brief gets the correction value for energy or pT for a specific /// \param inputCalibValue pT or energy of the photon that needs calibration + /// \param ctx Context which has the centrality, photontype and number of iterations stored inside + static float getCorrectionFactor(float inputCalibValue, const Context& ctx); + + /// \brief sets the parameters accordingly to the photon type, centrality and the wanted iteration level + /// \param photonType type of the photon (e.g. 0 for EMC) + /// \param cent centrality of the current collision in case the correction is centrality dependent + static const NonLinParams* resolveParams(PhotonType type, float cent); + + /// \brief sets the parameters accordingly to the photon type, centrality and the wanted iteration level for MC /// \param photonType type of the photon (e.g. 0 for EMC) - /// \param cent centrailty of the current collision in case the correction is centrality dependent - float getCorrectionFactor(float inputCalibValue, PhotonType photonType = PhotonType::kEMC, float cent = 0); + /// \param cent centrality of the current collision in case the correction is centrality dependent + static const NonLinParams* resolveParamsMC(PhotonType type, float cent); private: + static constexpr NonLinParams kNonLinTable + [PhotonN][CentBins][MaxIter] = + { + // ============================ + // PhotonType::kEMC (0) + // ============================ + { + // 00–10 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, // iter 0 + {0.f, 0.f, 0.f} // iter 1 + }, + // 10–20 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}, + // 20–30 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}, + // 30–40 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}, + // 40–50 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}, + // 50–60 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}, + // 60–70 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}, + // 70–80 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}, + // 80–90 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}, + // 90–100 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}}, + + // ============================ + // PhotonType::kPCM (1) + // ============================ + { + // 00–10 + { + {10.7203f, 0.0383968f, 10.6025f}, // iter 0 + {7.84549f, 0.0250021f, 7.86976f} // iter 1 + }, + // 10–20 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}, + // 20–30 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}, + // 30–40 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}, + // 40–50 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}, + // 50–60 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}, + // 60–70 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}, + // 70–80 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}, + // 80–90 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}, + // 90–100 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}}, + + // ============================ + // PhotonType::kPHOS (2) + // ============================ + { + // All centralities identical + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}}}; + + static constexpr NonLinParams kNonLinTableMC + [PhotonN][CentBins][MaxIter] = + { + // ============================ + // PhotonType::kEMC (0) + // ============================ + { + // 00–10 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, // iter 0 + {0.f, 0.f, 0.f} // iter 1 + }, + // 10–20 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}, + // 20–30 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}, + // 30–40 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}, + // 40–50 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}, + // 50–60 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}, + // 60–70 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}, + // 70–80 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}, + // 80–90 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}, + // 90–100 + { + {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, + {0.f, 0.f, 0.f}}}, + + // ============================ + // PhotonType::kPCM (1) + // ============================ + { + // 00–10 + { + {10.7203f, 0.0383968f, 10.6025f}, // iter 0 + {7.84549f, 0.0250021f, 7.86976f} // iter 1 + }, + // 10–20 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}, + // 20–30 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}, + // 30–40 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}, + // 40–50 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}, + // 50–60 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}, + // 60–70 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}, + // 70–80 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}, + // 80–90 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}, + // 90–100 + { + {10.7203f, 0.0383968f, 10.6025f}, + {7.84549f, 0.0250021f, 7.86976f}}}, + + // ============================ + // PhotonType::kPHOS (2) + // ============================ + { + // All centralities identical + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, + {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}}}; }; } // namespace o2::pwgem::nonlin diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCut.h b/PWGEM/PhotonMeson/Core/V0PhotonCut.h index ba430be368b..7f0d18d6d8e 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCut.h +++ b/PWGEM/PhotonMeson/Core/V0PhotonCut.h @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -149,6 +150,16 @@ static const std::vector labelsCutScore = {"score primary photons", } // namespace o2::analysis +namespace o2::analysis::em::v0 +{ + +template +concept IsNonLinIterator = o2::soa::is_iterator && requires(T t) { + // Check that the *elements* of the container have the required methods: + { t.corrPt() } -> std::same_as; +}; +} // namespace o2::analysis::em::v0 + class V0PhotonCut : public TNamed { public: @@ -688,7 +699,11 @@ class V0PhotonCut : public TNamed { switch (cut) { case V0PhotonCuts::kV0PtRange: - return v0.pt() >= mMinV0Pt && v0.pt() <= mMaxV0Pt; + if constexpr (o2::analysis::em::v0::IsNonLinIterator) { + return v0.corrPt() >= mMinV0Pt && v0.corrPt() <= mMaxV0Pt; + } else { + return v0.pt() >= mMinV0Pt && v0.pt() <= mMaxV0Pt; + } case V0PhotonCuts::kV0EtaRange: return v0.eta() >= mMinV0Eta && v0.eta() <= mMaxV0Eta; diff --git a/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx b/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx index 0561e60fc22..6c8132fb0b6 100644 --- a/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx +++ b/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx @@ -51,6 +51,8 @@ struct NonLinProducer { Produces tableNonLinClusters; Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3)"}; + Configurable emcIteration{"emcIteration", 0, "iteration number of the non lin correction for EMCal. 0 means first iteration 1 means second and so on!"}; + Configurable pcmIteration{"pcmIteration", 0, "iteration number of the non lin correction for PCM. 0 means first iteration 1 means second and so on!"}; HistogramRegistry historeg{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; @@ -62,16 +64,22 @@ struct NonLinProducer { EMNonLin emNonLinEMC; EMNonLin emNonLinPCM; + EMNonLin::Context emNonLinContextEMC; + EMNonLin::Context emNonLinContextPCM; + void init(o2::framework::InitContext&) { - historeg.add("QA/EMC/EIn", "Energy of clusters before cuts", gHistoSpecClusterE); - historeg.add("QA/EMC/EOut", "Energy of clusters after cuts", gHistoSpecClusterE); + historeg.add("QA/EMC/EIn", "Energy of EMC clusters before NonLin correction", gHistoSpecClusterE); + historeg.add("QA/EMC/EOut", "Energy of EMC clusters after NonLin correction", gHistoSpecClusterE); + + historeg.add("QA/EMC/PtIn", "Pt of EMC clusters before NonLin correction", gHistoSpecPt); + historeg.add("QA/EMC/PtOut", "Pt of EMC clusters after NonLin correction", gHistoSpecPt); - historeg.add("QA/EMC/PtIn", "Energy of clusters before cuts", gHistoSpecPt); - historeg.add("QA/EMC/PtOut", "Energy of clusters after cuts", gHistoSpecPt); + historeg.add("QA/PCM/PtIn", "Pt of PCM photon before NonLin correction", gHistoSpecPt); + historeg.add("QA/PCM/PtOut", "Pt of PCM photon after NonLin correction", gHistoSpecPt); - historeg.add("QA/PCM/PtIn", "Energy of clusters before cuts", gHistoSpecPt); - historeg.add("QA/PCM/PtOut", "Energy of clusters after cuts", gHistoSpecPt); + emNonLinContextEMC.setIter(emcIteration); + emNonLinContextPCM.setIter(pcmIteration); } /// Get the centrality @@ -101,33 +109,36 @@ struct NonLinProducer { template void runEMC(TClusters const& clusters, TCollisio& collision) { - float nonLinE = 0.f; - float nonLinPt = 0.f; - - float nonLinFactor = 1.f; + float cent = getCentrality(collision); int32_t collIndex = collision.globalIndex(); for (const auto& cluster : clusters) { + float nonLinE = 0.f; + float nonLinPt = 0.f; + float nonLinFactor = 1.f; // check that we are at the correct collision if (cluster.emeventId() != collIndex) { collIndex = cluster.emeventId(); collision.setCursor(collIndex); + cent = getCentrality(collision); } + emNonLinContextEMC.setParams(emNonLinEMC.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kEMC, cent)); + // fill before non lin histograms historeg.fill(HIST("QA/EMC/EIn"), cluster.e()); historeg.fill(HIST("QA/EMC/PtIn"), cluster.pt()); // get NonLin factor from class dependent on the centrality - nonLinFactor = emNonLinEMC.getCorrectionFactor(cluster.e(), o2::pwgem::nonlin::EMNonLin::PhotonType::kEMC, getCentrality(collision)); + nonLinFactor = emNonLinEMC.getCorrectionFactor(cluster.e(), emNonLinContextEMC); nonLinE = nonLinFactor * cluster.e(); nonLinPt = nonLinFactor * cluster.pt(); // fill after non lin histograms - historeg.fill(HIST("QA/EMC/EIn"), nonLinE); - historeg.fill(HIST("QA/EMC/PtIn"), nonLinPt); + historeg.fill(HIST("QA/EMC/EOut"), nonLinE); + historeg.fill(HIST("QA/EMC/PtOut"), nonLinPt); tableNonLinClusters(nonLinE, nonLinPt); } @@ -136,29 +147,32 @@ struct NonLinProducer { template void runPCM(TV0 const& v0s, TCollisio& collision) { - float nonLinPt = 0.f; - - float nonLinFactor = 1.f; + float cent = getCentrality(collision); int32_t collIndex = collision.globalIndex(); for (const auto& v0 : v0s) { + float nonLinPt = 0.f; + float nonLinFactor = 1.f; // check that we are at the correct collision if (v0.emeventId() != collIndex) { collIndex = v0.emeventId(); collision.setCursor(collIndex); + cent = getCentrality(collision); } + emNonLinContextPCM.setParams(emNonLinPCM.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM, cent)); + // fill before non lin histograms historeg.fill(HIST("QA/PCM/PtIn"), v0.pt()); // get NonLin factor from class dependent on the centrality - nonLinFactor = emNonLinEMC.getCorrectionFactor(v0.pt(), o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM, getCentrality(collision)); + nonLinFactor = emNonLinEMC.getCorrectionFactor(v0.pt(), emNonLinContextPCM); nonLinPt = nonLinFactor * v0.pt(); // fill after non lin histograms - historeg.fill(HIST("QA/PCM/PtIn"), nonLinPt); + historeg.fill(HIST("QA/PCM/PtOut"), nonLinPt); tableNonLinV0s(nonLinPt); } diff --git a/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx b/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx index d687db998f3..9520c3216e6 100644 --- a/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx +++ b/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx @@ -15,7 +15,6 @@ #include "PWGEM/PhotonMeson/Core/EMBitFlags.h" #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" -#include "PWGEM/PhotonMeson/Core/EMNonLin.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" #include "PWGEM/PhotonMeson/DataModel/GammaTablesRedux.h" @@ -69,7 +68,6 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photon; -using namespace o2::pwgem::nonlin; enum QvecEstimator { FT0M = 0, @@ -109,8 +107,6 @@ enum class MapLevel { }; struct CalibTaskEmc { - static constexpr float MinEnergy = 0.7f; - // configurable for flow Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3)"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -225,20 +221,17 @@ struct CalibTaskEmc { } correctionConfig; SliceCache cache; - EMNonLin emNonLin; o2::framework::Service ccdb; int runNow = 0; int runBefore = -1; Filter collisionFilter = (nabs(aod::collision::posZ) <= eventcuts.cfgZvtxMax) && (aod::evsel::ft0cOccupancyInTimeRange <= eventcuts.cfgFT0COccupancyMax) && (aod::evsel::ft0cOccupancyInTimeRange >= eventcuts.cfgFT0COccupancyMin); - using EMCalPhotons = soa::Join; - using PCMPhotons = soa::Join; + using EMCalPhotons = soa::Join; + using PCMPhotons = soa::Join; using FilteredCollsWithQvecs = soa::Filtered>; using CollsWithQvecs = soa::Join; using Colls = soa::Join; - static constexpr std::size_t NQVecEntries = 6; - PresliceOptional perCollisionEMC = o2::aod::emccluster::emeventId; PresliceOptional perCollisionPCM = aod::v0photonkf::emeventId; PresliceOptional perEMCClusterMT = o2::aod::mintm::minClusterId; @@ -256,16 +249,12 @@ struct CalibTaskEmc { static constexpr int NBinsPhi = 440; // (440 bins = 0.01 step size covering most regions) std::array lookupTable1D; - float epsilon = 1.e-8; - - // static constexpr - static constexpr int8_t NMinPhotonRotBkg = 3; // Usage when cfgEnableNonLin is enabled uint8_t nColl = 1; // To access the 1D array - inline int getIndex(int iEta, int iPhi) + static inline int getIndex(int iEta, int iPhi) { return iEta * NBinsPhi + iPhi; } @@ -368,7 +357,8 @@ struct CalibTaskEmc { const AxisSpec thnAxisCent{thnConfigAxisCent, "Centrality (%)"}; const AxisSpec thAxisTanThetaPhi{mesonConfig.thConfigAxisTanThetaPhi, "atan(#Delta#theta/#Delta#varphi)"}; const AxisSpec thAxisEnergyCalib{thnConfigAxisEnergyCalib, "#it{E}_{clus} (GeV)"}; - const AxisSpec thnAxisPtCalib{thnConfigAxisPtCalib, "#it{p}_{T} (GeV)"}; + const AxisSpec thnAxisPtCalib{thnConfigAxisPtCalib, "#it{p}_{T,#gamma} (GeV)"}; + const AxisSpec thnAxisPtCalibMeson{thnConfigAxisPtCalib, "#it{p}_{T,meson} (GeV)"}; const AxisSpec thAxisAlpha{100, -1., +1, "#alpha"}; const AxisSpec thAxisEnergy{1000, 0., 100., "#it{E}_{clus} (GeV)"}; const AxisSpec thAxisEta{320, -0.8, 0.8, "#eta"}; @@ -410,10 +400,10 @@ struct CalibTaskEmc { hMesonCutsMixed->GetXaxis()->SetBinLabel(6, "out"); if (mesonConfig.cfgEnableQA.value) { - registry.add("mesonQA/hInvMassPt", "Histo for inv pair mass vs pt", HistType::kTH2D, {thnAxisInvMass, thnAxisPtCalib}); + registry.add("mesonQA/hInvMassPt", "Histo for inv pair mass vs pt", HistType::kTH2D, {thnAxisInvMass, thnAxisPtCalibMeson}); registry.add("mesonQA/hTanThetaPhi", "Histo for identification of conversion cluster", HistType::kTH2D, {thnAxisInvMass, thAxisTanThetaPhi}); registry.add("mesonQA/hAlphaPt", "Histo of meson asymmetry vs pT", HistType::kTH2D, {thAxisAlpha, thnAxisPtCalib}); - registry.add("mesonQA/hInvMassPtMixed", "Histo for inv pair mass vs pt for mixed event", HistType::kTH2D, {thnAxisInvMass, thnAxisPtCalib}); + registry.add("mesonQA/hInvMassPtMixed", "Histo for inv pair mass vs pt for mixed event", HistType::kTH2D, {thnAxisInvMass, thnAxisPtCalibMeson}); registry.add("mesonQA/hTanThetaPhiMixed", "Histo for identification of conversion cluster for mixed event", HistType::kTH2D, {thnAxisInvMass, thAxisTanThetaPhi}); registry.add("mesonQA/hAlphaPtMixed", "Histo of meson asymmetry vs pT for mixed event", HistType::kTH2D, {thAxisAlpha, thnAxisPtCalib}); } @@ -428,7 +418,7 @@ struct CalibTaskEmc { /// Change radians to degree /// \param angle in radians /// \return angle in degree - constexpr float getAngleDegree(float angle) + static constexpr float getAngleDegree(float angle) { return angle * o2::constants::math::Rad2Deg; } @@ -636,9 +626,9 @@ struct CalibTaskEmc { continue; } if (mesonConfig.cfgEnableQA.value) { - registry.fill(HIST("mesonQA/hInvMassPt"), vMeson.M(), vMeson.Pt()); + registry.fill(HIST("mesonQA/hInvMassPt"), vMeson.M(), g1.corrPt()); registry.fill(HIST("mesonQA/hTanThetaPhi"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); - registry.fill(HIST("mesonQA/hAlphaPt"), asymmetry, vMeson.Pt()); + registry.fill(HIST("mesonQA/hAlphaPt"), asymmetry, g1.corrPt()); } if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { registry.fill(HIST("hMesonCuts"), 5); @@ -747,9 +737,9 @@ struct CalibTaskEmc { continue; } if (mesonConfig.cfgEnableQA.value) { - registry.fill(HIST("mesonQA/hInvMassPtMixed"), vMeson.M(), vMeson.Pt()); + registry.fill(HIST("mesonQA/hInvMassPtMixed"), vMeson.M(), g1.corrPt()); registry.fill(HIST("mesonQA/hTanThetaPhiMixed"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); - registry.fill(HIST("mesonQA/hAlphaPtMixed"), asymmetry, vMeson.Pt()); + registry.fill(HIST("mesonQA/hAlphaPtMixed"), asymmetry, g1.corrPt()); } if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { registry.fill(HIST("hMesonCutsMixed"), 5); @@ -765,9 +755,6 @@ struct CalibTaskEmc { // PCM-EMCal same event void processEMCalPCMC(CollsWithQvecs const& collisions, EMCalPhotons const& clusters, PCMPhotons const& photons, aod::V0Legs const&, MinMTracks const& matchedPrims, MinMSTracks const& matchedSeconds) { - float corrNonLin1 = 1.f; - float corrNonLin2 = 1.f; - if (clusters.size() <= 0 && photons.size() <= 0) { LOG(info) << "Skipping DF because there are not photons!"; return; @@ -808,21 +795,10 @@ struct CalibTaskEmc { } } - if (correctionConfig.cfgEnableNonLinEMC) { - corrNonLin1 = emNonLin.getCorrectionFactor(g1.e(), o2::pwgem::nonlin::EMNonLin::PhotonType::kEMC, getCentrality(collision)); - } - - if (correctionConfig.cfgEnableNonLinPCM) { - corrNonLin2 = emNonLin.getCorrectionFactor(g2.pt(), o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM, getCentrality(collision)); - } - - float photon1Pt = corrNonLin1 * g1.pt(); - float photon2Pt = corrNonLin2 * g2.pt(); - // EMCal photon v1 - ROOT::Math::PtEtaPhiMVector v1(photon1Pt, g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v1(g1.corrPt(), g1.eta(), g1.phi(), 0.); // PCM photon v2s - ROOT::Math::PtEtaPhiMVector v2(photon2Pt, g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.corrPt(), g2.eta(), g2.phi(), 0.); ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; float dTheta = v1.Theta() - v2.Theta(); @@ -838,15 +814,15 @@ struct CalibTaskEmc { continue; } if (mesonConfig.cfgEnableQA.value) { - registry.fill(HIST("mesonQA/hInvMassPt"), vMeson.M(), vMeson.Pt()); + registry.fill(HIST("mesonQA/hInvMassPt"), vMeson.M(), g1.corrPt()); registry.fill(HIST("mesonQA/hTanThetaPhi"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); - registry.fill(HIST("mesonQA/hAlphaPt"), (v1.E() - v2.E()) / (v1.E() + v2.E()), vMeson.Pt()); + registry.fill(HIST("mesonQA/hAlphaPt"), (v1.E() - v2.E()) / (v1.E() + v2.E()), g1.corrPt()); } if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { registry.fill(HIST("hMesonCuts"), 5); continue; } - runFlowAnalysis<0>(collision, vMeson, corrNonLin1 * g1.e()); + runFlowAnalysis<0>(collision, vMeson, g1.corrE()); } } } @@ -855,9 +831,6 @@ struct CalibTaskEmc { // PCM-EMCal mixed event void processEMCalPCMMixed(CollsWithQvecs const& collisions, EMCalPhotons const& clusters, PCMPhotons const& pcmPhotons, aod::V0Legs const&, MinMTracks const& matchedPrims, MinMSTracks const& matchedSeconds) { - float corrNonLin1 = 1.f; - float corrNonLin2 = 1.f; - if (clusters.size() <= 0 && pcmPhotons.size() <= 0) { LOG(info) << "Skipping DF because there are not photons!"; return; @@ -909,16 +882,8 @@ struct CalibTaskEmc { } } - if (correctionConfig.cfgEnableNonLinEMC) { - corrNonLin1 = emNonLin.getCorrectionFactor(g1.e(), o2::pwgem::nonlin::EMNonLin::PhotonType::kEMC, getCentrality(c1)); - } - - if (correctionConfig.cfgEnableNonLinPCM) { - corrNonLin2 = emNonLin.getCorrectionFactor(g2.pt(), o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM, getCentrality(c2)); - } - - float photon1Pt = corrNonLin1 * g1.pt(); - float photon2Pt = corrNonLin2 * g2.pt(); + float photon1Pt = g1.corrPt(); + float photon2Pt = g2.corrPt(); ROOT::Math::PtEtaPhiMVector v1(photon1Pt, g1.eta(), g1.phi(), 0.); ROOT::Math::PtEtaPhiMVector v2(photon2Pt, g2.eta(), g2.phi(), 0.); @@ -938,16 +903,16 @@ struct CalibTaskEmc { continue; } if (mesonConfig.cfgEnableQA.value) { - registry.fill(HIST("mesonQA/hInvMassPtMixed"), vMeson.M(), vMeson.Pt()); + registry.fill(HIST("mesonQA/hInvMassPtMixed"), vMeson.M(), photon1Pt); registry.fill(HIST("mesonQA/hTanThetaPhiMixed"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); - registry.fill(HIST("mesonQA/hAlphaPtMixed"), (v1.E() - v2.E()) / (v1.E() + v2.E()), vMeson.Pt()); + registry.fill(HIST("mesonQA/hAlphaPtMixed"), (v1.E() - v2.E()) / (v1.E() + v2.E()), photon1Pt); } if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { registry.fill(HIST("hMesonCutsMixed"), 5); continue; } registry.fill(HIST("hMesonCutsMixed"), 6); - runFlowAnalysis<2>(c1, vMeson, corrNonLin1 * g1.e()); + runFlowAnalysis<2>(c1, vMeson, g1.corrE()); } } } @@ -956,9 +921,6 @@ struct CalibTaskEmc { // Pi0 from EMCal void processPCM(CollsWithQvecs const& collisions, PCMPhotons const& photons, aod::V0Legs const&) { - float corrNonLin1 = 1.f; - float corrNonLin2 = 1.f; - if (photons.size() <= 0) { LOG(info) << "Skipping DF because there are not photons!"; return; @@ -982,13 +944,8 @@ struct CalibTaskEmc { continue; } - if (correctionConfig.cfgEnableNonLinPCM) { - corrNonLin1 = emNonLin.getCorrectionFactor(g1.pt(), o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM, getCentrality(collision)); - corrNonLin2 = emNonLin.getCorrectionFactor(g2.pt(), o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM, getCentrality(collision)); - } - - float photon1Pt = corrNonLin1 * g1.pt(); - float photon2Pt = corrNonLin2 * g2.pt(); + float photon1Pt = g1.corrPt(); + float photon2Pt = g2.corrPt(); float asymmetry = (photon1Pt - photon2Pt) / (photon1Pt + photon2Pt); if (std::fabs(asymmetry) > cfgMaxAsymmetry) { // only use symmetric decays @@ -1011,8 +968,8 @@ struct CalibTaskEmc { continue; } if (mesonConfig.cfgEnableQA.value) { - registry.fill(HIST("mesonQA/hInvMassPt"), vMeson.M(), vMeson.Pt()); - registry.fill(HIST("mesonQA/hAlphaPt"), asymmetry, vMeson.Pt()); + registry.fill(HIST("mesonQA/hInvMassPt"), vMeson.M(), photon1Pt); + registry.fill(HIST("mesonQA/hAlphaPt"), asymmetry, photon1Pt); } registry.fill(HIST("hMesonCuts"), 6); runFlowAnalysis<0>(collision, vMeson, photon1Pt); @@ -1024,8 +981,6 @@ struct CalibTaskEmc { // PCM-EMCal mixed event void processPCMMixed(FilteredCollsWithQvecs const& collisions, PCMPhotons const& pcmPhotons, aod::V0Legs const&) { - float corrNonLin1 = 1.f; - float corrNonLin2 = 1.f; if (pcmPhotons.size() <= 0) { LOG(info) << "Skipping DF because there are not photons!"; return; @@ -1063,13 +1018,8 @@ struct CalibTaskEmc { continue; } - if (correctionConfig.cfgEnableNonLinPCM) { - corrNonLin1 = emNonLin.getCorrectionFactor(g1.pt(), o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM, getCentrality(c1)); - corrNonLin2 = emNonLin.getCorrectionFactor(g2.pt(), o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM, getCentrality(c2)); - } - - float photon1Pt = corrNonLin1 * g1.pt(); - float photon2Pt = corrNonLin2 * g2.pt(); + float photon1Pt = g1.corrPt(); + float photon2Pt = g2.corrPt(); float asymmetry = (photon1Pt - photon2Pt) / (photon1Pt + photon2Pt); if (std::fabs(asymmetry) > cfgMaxAsymmetry) { // only use symmetric decays @@ -1092,8 +1042,8 @@ struct CalibTaskEmc { continue; } if (mesonConfig.cfgEnableQA.value) { - registry.fill(HIST("mesonQA/hInvMassPtMixed"), vMeson.M(), vMeson.Pt()); - registry.fill(HIST("mesonQA/hAlphaPtMixed"), asymmetry, vMeson.Pt()); + registry.fill(HIST("mesonQA/hInvMassPtMixed"), vMeson.M(), photon1Pt); + registry.fill(HIST("mesonQA/hAlphaPtMixed"), asymmetry, photon1Pt); } registry.fill(HIST("hMesonCutsMixed"), 6); runFlowAnalysis<2>(c1, vMeson, photon1Pt); diff --git a/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx b/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx index dfb0d5532ec..6126cd516b2 100644 --- a/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx @@ -59,7 +59,6 @@ #include #include #include -#include #include #include #include @@ -111,8 +110,6 @@ enum class MapLevel { }; struct TaskPi0FlowEMC { - static constexpr float MinEnergy = 0.7f; - // configurable for flow Configurable harmonic{"harmonic", 2, "harmonic number"}; Configurable qvecDetector{"qvecDetector", 0, "Detector for Q vector estimation (FT0M: 0, FT0A: 1, FT0C: 2, TPC Pos: 3, TPC Neg: 4, TPC Tot: 5, FV0A: 6)"}; @@ -124,7 +121,6 @@ struct TaskPi0FlowEMC { Configurable cfgEMCalMapLevelSameEvent{"cfgEMCalMapLevelSameEvent", 4, "Different levels of correction for the same event, the smaller number includes the level of the higher number (4: none, 3: only inside EMCal, 2: remove edges, 1: exclude bad channels)"}; Configurable cfgDistanceToEdge{"cfgDistanceToEdge", 1, "Distance to edge in cells required for rotated cluster to be accepted"}; Configurable cfgDoM02{"cfgDoM02", false, "Flag to enable flow vs M02 for single photons"}; - Configurable cfgDoReverseScaling{"cfgDoReverseScaling", false, "Flag to reverse the scaling that is possibly applied during NonLin"}; Configurable cfgDoPlaneQA{"cfgDoPlaneQA", false, "Flag to enable QA plots comparing in and out of plane"}; Configurable cfgMaxQVector{"cfgMaxQVector", 20.f, "Maximum allowed absolute QVector value."}; Configurable cfgMaxAsymmetry{"cfgMaxAsymmetry", 0.1f, "Maximum allowed asymmetry for photon pairs used in calibration."}; @@ -259,8 +255,8 @@ struct TaskPi0FlowEMC { // Filter clusterFilter = aod::skimmedcluster::time >= emccuts.cfgEMCminTime && aod::skimmedcluster::time <= emccuts.cfgEMCmaxTime && aod::skimmedcluster::m02 >= emccuts.cfgEMCminM02 && aod::skimmedcluster::m02 <= emccuts.cfgEMCmaxM02 && aod::skimmedcluster::e >= emccuts.cfgEMCminE; Filter collisionFilter = (nabs(aod::collision::posZ) <= eventcuts.cfgZvtxMax) && (aod::evsel::ft0cOccupancyInTimeRange <= eventcuts.cfgFT0COccupancyMax) && (aod::evsel::ft0cOccupancyInTimeRange >= eventcuts.cfgFT0COccupancyMin); // using FilteredEMCalPhotons = soa::Filtered>; - using EMCalPhotons = soa::Join; - using PCMPhotons = soa::Join; + using EMCalPhotons = soa::Join; + using PCMPhotons = soa::Join; using FilteredCollsWithQvecs = soa::Filtered>; using CollsWithQvecs = soa::Join; using Colls = soa::Join; @@ -290,13 +286,10 @@ struct TaskPi0FlowEMC { // static constexpr static constexpr int8_t NMinPhotonRotBkg = 3; - // Usage when cfgEnableNonLin is enabled - std::unique_ptr fEMCalCorrectionFactor; // ("fEMCalCorrectionFactor","(1 + [0]/x + [1]/x^2) / (1 + [2]/x)", 0.3, 100.); - float energyCorrectionFactor = 1.f; uint8_t nColl = 1; // To access the 1D array - inline int getIndex(int iEta, int iPhi) + static inline int getIndex(int iEta, int iPhi) { return iEta * NBinsPhi + iPhi; } @@ -484,14 +477,12 @@ struct TaskPi0FlowEMC { LOG(info) << "thnConfigAxisInvMass.value[1] = " << thnConfigAxisInvMass.value[1] << " thnConfigAxisInvMass.value.back() = " << thnConfigAxisInvMass.value.back(); LOG(info) << "thnConfigAxisPt.value[1] = " << thnConfigAxisPt.value[1] << " thnConfigAxisPt.value.back() = " << thnConfigAxisPt.value.back(); - fEMCalCorrectionFactor = std::make_unique("fEMCalCorrectionFactor", "(1 + [0]/x + [1]/x^2) / (1 + [2]/x)", 0.3, 100.); - fEMCalCorrectionFactor->SetParameters(-5.33426e-01, 1.40144e-02, -5.24434e-01); }; // end init /// Change radians to degree /// \param angle in radians /// \return angle in degree - constexpr float getAngleDegree(float angle) + static constexpr float getAngleDegree(float angle) { return angle * o2::constants::math::Rad2Deg; } @@ -744,7 +735,7 @@ struct TaskPi0FlowEMC { } /// \brief Calculate background using rotation background method - template + template void rotationBackground(const ROOT::Math::PtEtaPhiMVector& meson, ROOT::Math::PtEtaPhiMVector photon1, ROOT::Math::PtEtaPhiMVector photon2, TPhotons const& photonsColl, unsigned int ig1, unsigned int ig2, TCollision const& collision) { // if less than 3 clusters are present skip event since we need at least 3 clusters @@ -795,11 +786,7 @@ struct TaskPi0FlowEMC { if (checkEtaPhi1D(photon.eta(), RecoDecay::constrainAngle(photon.phi())) >= cfgEMCalMapLevelBackground.value) { continue; } - energyCorrectionFactor = 1.f; - if (correctionConfig.cfgEnableNonLin.value) { - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(photon.e() > MinEnergy ? photon.e() : MinEnergy); - } - ROOT::Math::PtEtaPhiMVector photon3(energyCorrectionFactor * photon.pt(), photon.eta(), photon.phi(), 0.); + ROOT::Math::PtEtaPhiMVector photon3(photon.corrPt(), photon.eta(), photon.phi(), 0.); if (iCellIDPhoton1 >= 0) { ROOT::Math::PtEtaPhiMVector mother1 = photon1 + photon3; float openingAngle1 = std::acos(photon1.Vect().Dot(photon3.Vect()) / (photon1.P() * photon3.P())); @@ -812,10 +799,10 @@ struct TaskPi0FlowEMC { } if (openingAngle1 > mesonConfig.minOpenAngle && thnConfigAxisInvMass.value[1] <= mother1.M() && thnConfigAxisInvMass.value.back() >= mother1.M() && thnConfigAxisPt.value[1] <= mother1.Pt() && thnConfigAxisPt.value.back() >= mother1.Pt()) { - if (mesonConfig.enableTanThetadPhi) { + if (mesonConfig.enableTanThetadPhi.value) { float dTheta = photon1.Theta() - photon3.Theta(); float dPhi = photon1.Phi() - photon3.Phi(); - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi <= std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + if (mesonConfig.enableTanThetadPhi.value && mesonConfig.minTanThetadPhi <= std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { continue; } } @@ -834,10 +821,10 @@ struct TaskPi0FlowEMC { } if (openingAngle2 > mesonConfig.minOpenAngle && thnConfigAxisInvMass.value[1] <= mother2.M() && thnConfigAxisInvMass.value.back() >= mother2.M() && thnConfigAxisPt.value[1] <= mother2.Pt() && thnConfigAxisPt.value.back() >= mother2.Pt()) { - if (mesonConfig.enableTanThetadPhi) { + if (mesonConfig.enableTanThetadPhi.value) { float dTheta = photon2.Theta() - photon3.Theta(); float dPhi = photon2.Phi() - photon3.Phi(); - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi <= std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + if (mesonConfig.enableTanThetadPhi.value && mesonConfig.minTanThetadPhi <= std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { continue; } } @@ -859,7 +846,7 @@ struct TaskPi0FlowEMC { /// \param giPCM global index of photonPCM /// \param giEMC global index of photonEMC /// \param collision current collision iterator - template + template void rotationBackgroundPCMEMC(const ROOT::Math::PtEtaPhiMVector& meson, ROOT::Math::PtEtaPhiMVector photonPCM, ROOT::Math::PtEtaPhiMVector photonEMC, TPCMPhotons const& photonsCollPCM, TEMCPhotons const& photonsCollEMC, unsigned int giPCM, unsigned int giEMC, TCollision const& collision) { // if less than 3 photon candidates are present skip event since we need at least 3 candidates @@ -908,11 +895,7 @@ struct TaskPi0FlowEMC { if (checkEtaPhi1D(photon.eta(), RecoDecay::constrainAngle(photon.phi())) >= cfgEMCalMapLevelBackground.value) { continue; } - energyCorrectionFactor = 1.f; - if (correctionConfig.cfgEnableNonLin.value) { - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(photon.e() > MinEnergy ? photon.e() : MinEnergy); - } - ROOT::Math::PtEtaPhiMVector photon3(energyCorrectionFactor * photon.pt(), photon.eta(), photon.phi(), 0.); + ROOT::Math::PtEtaPhiMVector photon3(photon.corrPt(), photon.eta(), photon.phi(), 0.); ROOT::Math::PtEtaPhiMVector mother1 = photonPCM + photon3; float openingAngle = std::acos(photonPCM.Vect().Dot(photon3.Vect()) / (photonPCM.P() * photon3.P())); float cosNPhi = std::cos(harmonic * mother1.Phi()); @@ -923,10 +906,10 @@ struct TaskPi0FlowEMC { scalprodCand = scalprodCand / h1SPResolution->GetBinContent(h1SPResolution->FindBin(cent + epsilon)); } if (openingAngle > mesonConfig.minOpenAngle && thnConfigAxisInvMass.value[1] <= mother1.M() && thnConfigAxisInvMass.value.back() >= mother1.M() && thnConfigAxisPt.value[1] <= mother1.Pt() && thnConfigAxisPt.value.back() >= mother1.Pt()) { - if (mesonConfig.enableTanThetadPhi) { + if (mesonConfig.enableTanThetadPhi.value) { float dTheta = photonPCM.Theta() - photon3.Theta(); float dPhi = photonPCM.Phi() - photon3.Phi(); - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi <= std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + if (mesonConfig.enableTanThetadPhi.value && mesonConfig.minTanThetadPhi <= std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { continue; } } @@ -955,10 +938,10 @@ struct TaskPi0FlowEMC { scalprodCand = scalprodCand / h1SPResolution->GetBinContent(h1SPResolution->FindBin(cent + epsilon)); } if (openingAngle > mesonConfig.minOpenAngle && thnConfigAxisInvMass.value[1] <= mother1.M() && thnConfigAxisInvMass.value.back() >= mother1.M() && thnConfigAxisPt.value[1] <= mother1.Pt() && thnConfigAxisPt.value.back() >= mother1.Pt()) { - if (mesonConfig.enableTanThetadPhi) { + if (mesonConfig.enableTanThetadPhi.value) { float dTheta = photonEMC.Theta() - photon3.Theta(); float dPhi = photonEMC.Phi() - photon3.Phi(); - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi <= std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + if (mesonConfig.enableTanThetadPhi.value && mesonConfig.minTanThetadPhi <= std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { continue; } } @@ -1004,7 +987,7 @@ struct TaskPi0FlowEMC { /// \brief check if standard event cuts + FT0 occupancy + centrality + QVec good is /// \param collision collision that will be checked /// \return true if collision survives all checks, otherwise false - template + template bool isFullEventSelected(TCollision const& collision, bool fillHisto = false) { if (fillHisto) { @@ -1035,7 +1018,7 @@ struct TaskPi0FlowEMC { return true; } - template + template void runPairingLoop(TCollision const& collision, TPhotons1 const& photons1, TPhotons2 const& photons2, EMBitFlags const& flags1, EMBitFlags const& flags2) { for (const auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photons1, photons2))) { @@ -1052,15 +1035,8 @@ struct TaskPi0FlowEMC { continue; } } - if (correctionConfig.cfgEnableNonLin.value) { - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g1.e() > MinEnergy ? g1.e() : MinEnergy); - } - if (correctionConfig.cfgEnableNonLin.value) { - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g2.e() > MinEnergy ? g2.e() : MinEnergy); - } - - ROOT::Math::PtEtaPhiMVector v1(energyCorrectionFactor * g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(energyCorrectionFactor * g2.pt(), g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v1(g1.corrPt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.corrPt(), g2.eta(), g2.phi(), 0.); ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; float dTheta = v1.Theta() - v2.Theta(); @@ -1088,7 +1064,7 @@ struct TaskPi0FlowEMC { registry.fill(HIST("mesonQA/hTanThetaPhi"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); registry.fill(HIST("mesonQA/hAlphaPt"), (v1.E() - v2.E()) / (v1.E() + v2.E()), vMeson.Pt()); } - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + if (mesonConfig.enableTanThetadPhi.value && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { registry.fill(HIST("hMesonCuts"), 5); continue; } @@ -1107,10 +1083,6 @@ struct TaskPi0FlowEMC { EMBitFlags flags(clusters.size()); fEMCCut.AreSelectedRunning(flags, clusters, matchedPrims, matchedSeconds, ®istry); - energyCorrectionFactor = 1.f; - if (cfgDoReverseScaling.value) { - energyCorrectionFactor = 1.0505f; - } for (const auto& collision : collisions) { if (!isFullEventSelected(collision, true)) { @@ -1126,7 +1098,7 @@ struct TaskPi0FlowEMC { if (emccuts.cfgEnableQA.value) { for (const auto& photon : photonsPerCollision) { - registry.fill(HIST("clusterQA/hEClusterBefore"), photon.e()); // before cuts + registry.fill(HIST("clusterQA/hEClusterBefore"), photon.corrE()); // before cuts registry.fill(HIST("clusterQA/hClusterEtaPhiBefore"), photon.phi(), photon.eta()); // before cuts if (!(fEMCCut.IsSelected(photon))) { continue; @@ -1134,7 +1106,7 @@ struct TaskPi0FlowEMC { if (cfgDistanceToEdge.value && (checkEtaPhi1D(photon.eta(), RecoDecay::constrainAngle(photon.phi())) >= cfgEMCalMapLevelSameEvent.value)) { continue; } - registry.fill(HIST("clusterQA/hEClusterAfter"), photon.e()); // accepted after cuts + registry.fill(HIST("clusterQA/hEClusterAfter"), photon.corrE()); // accepted after cuts registry.fill(HIST("clusterQA/hClusterEtaPhiAfter"), photon.phi(), photon.eta()); // after cuts } } @@ -1159,10 +1131,6 @@ struct TaskPi0FlowEMC { } EMBitFlags flags(clusters.size()); fEMCCut.AreSelectedRunning(flags, clusters, matchedPrims, matchedSeconds); - energyCorrectionFactor = 1.f; - if (cfgDoReverseScaling.value) { - energyCorrectionFactor = 1.0505f; - } using BinningType = ColumnBinningPolicy>; BinningType binningMixedEvent{{mixingConfig.cfgVtxBins, mixingConfig.cfgCentBins, mixingConfig.cfgEPBins}, true}; @@ -1206,14 +1174,8 @@ struct TaskPi0FlowEMC { continue; } } - if (correctionConfig.cfgEnableNonLin.value) { - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g1.e() > MinEnergy ? g1.e() : MinEnergy); - } - ROOT::Math::PtEtaPhiMVector v1(energyCorrectionFactor * g1.pt(), g1.eta(), g1.phi(), 0.); - if (correctionConfig.cfgEnableNonLin.value) { - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g2.e() > MinEnergy ? g2.e() : MinEnergy); - } - ROOT::Math::PtEtaPhiMVector v2(energyCorrectionFactor * g2.pt(), g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v1(g1.corrPt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.corrPt(), g2.eta(), g2.phi(), 0.); ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; float dTheta = v1.Theta() - v2.Theta(); @@ -1238,7 +1200,7 @@ struct TaskPi0FlowEMC { registry.fill(HIST("mesonQA/hTanThetaPhiMixed"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); registry.fill(HIST("mesonQA/hAlphaPtMixed"), (v1.E() - v2.E()) / (v1.E() + v2.E()), vMeson.Pt()); } - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + if (mesonConfig.enableTanThetadPhi.value && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { registry.fill(HIST("hMesonCutsMixed"), 5); continue; } @@ -1266,10 +1228,6 @@ struct TaskPi0FlowEMC { fV0PhotonCut.AreSelectedRunning(v0flags, photons, ®istry); } - energyCorrectionFactor = 1.f; - if (cfgDoReverseScaling.value) { - energyCorrectionFactor = 1.0505f; - } for (const auto& collision : collisions) { if (!isFullEventSelected(collision, true)) { @@ -1306,10 +1264,9 @@ struct TaskPi0FlowEMC { } // EMCal photon v1 - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g1.e() > MinEnergy ? g1.e() : MinEnergy); - ROOT::Math::PtEtaPhiMVector v1(energyCorrectionFactor * g1.pt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v1(g1.corrPt(), g1.eta(), g1.phi(), 0.); // PCM photon v2s - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.corrPt(), g2.eta(), g2.phi(), 0.); ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; float dTheta = v1.Theta() - v2.Theta(); @@ -1336,7 +1293,7 @@ struct TaskPi0FlowEMC { registry.fill(HIST("mesonQA/hTanThetaPhi"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); registry.fill(HIST("mesonQA/hAlphaPt"), (v1.E() - v2.E()) / (v1.E() + v2.E()), vMeson.Pt()); } - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + if (mesonConfig.enableTanThetadPhi.value && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { registry.fill(HIST("hMesonCuts"), 5); continue; } @@ -1361,7 +1318,6 @@ struct TaskPi0FlowEMC { Pair pairPCMEMC{binningOnPositions, mixingConfig.cfgMixingDepth, -1, collisions, associatedTables, &cache}; // indicates that mixingConfig.cfgMixingDepth events should be mixed and under/overflow (-1) to be ignored - energyCorrectionFactor = 1.f; EMBitFlags emcFlags(clusters.size()); if (clusters.size() > 0) { fEMCCut.AreSelectedRunning(emcFlags, clusters, matchedPrims, matchedSeconds, ®istry); @@ -1401,9 +1357,8 @@ struct TaskPi0FlowEMC { continue; } } - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g1.e() > MinEnergy ? g1.e() : MinEnergy); - ROOT::Math::PtEtaPhiMVector v1(energyCorrectionFactor * g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v1(g1.corrPt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.corrPt(), g2.eta(), g2.phi(), 0.); ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; float dTheta = v1.Theta() - v2.Theta(); @@ -1428,7 +1383,7 @@ struct TaskPi0FlowEMC { registry.fill(HIST("mesonQA/hTanThetaPhiMixed"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); registry.fill(HIST("mesonQA/hAlphaPtMixed"), (v1.E() - v2.E()) / (v1.E() + v2.E()), vMeson.Pt()); } - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + if (mesonConfig.enableTanThetadPhi.value && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { registry.fill(HIST("hMesonCutsMixed"), 5); continue; } @@ -1498,7 +1453,6 @@ struct TaskPi0FlowEMC { } auto [xQVec, yQVec] = getQvec(collision, qvecDetector); - float cent = getCentrality(collision); float phiCand = photon.phi(); @@ -1590,8 +1544,6 @@ struct TaskPi0FlowEMC { auto pcmPhotonTuple = std::make_tuple(pcmPhotons); SameKindPair pair{binningMixedEvent, mixingConfig.cfgMixingDepth, -1, collisions, pcmPhotonTuple, &cache}; // indicates that 5 events should be mixed and under/overflow (-1) to be ignored - energyCorrectionFactor = 1.f; - EMBitFlags v0flags(pcmPhotons.size()); fV0PhotonCut.AreSelectedRunning(v0flags, pcmPhotons); @@ -1618,9 +1570,8 @@ struct TaskPi0FlowEMC { if (!(v0flags.test(g1.globalIndex())) || !(v0flags.test(g2.globalIndex()))) { continue; } - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g1.e() > MinEnergy ? g1.e() : MinEnergy); - ROOT::Math::PtEtaPhiMVector v1(energyCorrectionFactor * g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v1(g1.corrPt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.corrPt(), g2.eta(), g2.phi(), 0.); ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; float openingAngle = std::acos(v1.Vect().Dot(v2.Vect()) / (v1.P() * v2.P()));