|
| 1 | +// Copyright 2019-2025 CERN and copyright holders of ALICE O2. |
| 2 | +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. |
| 3 | +// All rights not expressly granted are reserved. |
| 4 | +// |
| 5 | +// This software is distributed under the terms of the GNU General Public |
| 6 | +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". |
| 7 | +// |
| 8 | +// In applying this license CERN does not waive the privileges and immunities |
| 9 | +// granted to it by virtue of its status as an Intergovernmental Organization |
| 10 | +// or submit itself to any jurisdiction. |
| 11 | + |
| 12 | +/// \file FemtoFlowAngularContainer.h |
| 13 | +/// \brief Definition of the FemtoFlowAngularContainer |
| 14 | +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de |
| 15 | +/// \author Valentina Mantovani Sarti, valentina.mantovani-sarti@tum.de |
| 16 | +/// \author Georgios Mantzaridis, TU München, georgios.mantzaridis@tum.de |
| 17 | +/// \author Anton Riedel, TU München, anton.riedel@tum.de |
| 18 | +/// \author Zuzanna Chochulska, WUT Warsaw & CTU Prague, zchochul@cern.ch |
| 19 | + |
| 20 | +#ifndef PWGCF_FEMTOFLOW_CORE_FEMTOFLOWANGULARCONTAINER_H_ |
| 21 | +#define PWGCF_FEMTOFLOW_CORE_FEMTOFLOWANGULARCONTAINER_H_ |
| 22 | + |
| 23 | +#include <fairlogger/Logger.h> |
| 24 | +#include <vector> |
| 25 | +#include <string> |
| 26 | + |
| 27 | +#include "Framework/HistogramRegistry.h" |
| 28 | +#include "Common/Core/RecoDecay.h" |
| 29 | +#include "PWGCF/Femto/Core/FemtoFlowMath.h" |
| 30 | + |
| 31 | +#include "Math/Vector4D.h" |
| 32 | +#include "TMath.h" |
| 33 | +#include "TDatabasePDG.h" |
| 34 | + |
| 35 | +using namespace o2::framework; |
| 36 | + |
| 37 | +namespace o2::analysis::femto_flow |
| 38 | +{ |
| 39 | + |
| 40 | +namespace femto_flow_angular_container |
| 41 | +{ |
| 42 | +/// Femtoscopic observable to be computed |
| 43 | +enum Observable { kstar ///< kstar |
| 44 | +}; |
| 45 | + |
| 46 | +/// Type of the event processind |
| 47 | +enum EventType { same, ///< Pair from same event |
| 48 | + mixed ///< Pair from mixed event |
| 49 | +}; |
| 50 | +}; // namespace femto_flow_angular_container |
| 51 | + |
| 52 | +/// \class FemtoFlowAngularContainer |
| 53 | +/// \brief Container for all histogramming related to the correlation function. The two |
| 54 | +/// particles of the pair are passed here, and the correlation function and QA histograms |
| 55 | +/// are filled according to the specified observable |
| 56 | +/// \tparam eventType Type of the event (same/mixed) |
| 57 | +/// \tparam obs Observable to be computed (k*/Q_inv/...) |
| 58 | +template <femto_flow_angular_container::EventType eventType, femto_flow_angular_container::Observable obs> |
| 59 | +class FemtoFlowAngularContainer |
| 60 | +{ |
| 61 | + public: |
| 62 | + /// Destructor |
| 63 | + virtual ~FemtoFlowAngularContainer() = default; |
| 64 | + |
| 65 | + /// Initializes histograms for the task |
| 66 | + /// Called by init both in case of reconstructed data/ Monte Carlo, and for Monte Carlo Truth |
| 67 | + /// \tparam T type of the axis Object |
| 68 | + /// \param folderName Name of the directory in the output file (no suffix for reconstructed data/ Monte Carlo; "_MC" for Monte Carlo Truth) |
| 69 | + /// \param femtoObs Title of the femto observable axis |
| 70 | + /// \param femtoObsAxis axis object for the femto observable axis |
| 71 | + /// \param multAxis axis object for the multiplicity axis |
| 72 | + /// \param kTAxis axis object for the kT axis |
| 73 | + /// \param mTAxis axis object for the mT axis |
| 74 | + template <typename T> |
| 75 | + void initBase(std::string folderName, std::string /*femtoObs*/, T /*femtoObsAxis*/, T /*multAxis*/, T /*kTAxis*/, T /*mTAxis*/, T /*multAxis3D*/, T /*mTAxis3D*/, T etaAxis, T phiAxis, bool use3dplots) |
| 76 | + { |
| 77 | + mHistogramRegistry->add((folderName + "/DeltaEtaDeltaPhi").c_str(), "; #Delta#varphi (rad); #Delta#eta", kTH2F, {phiAxis, etaAxis}); |
| 78 | + if (use3dplots) { |
| 79 | + // use 3d plots |
| 80 | + } |
| 81 | + } |
| 82 | + |
| 83 | + /// Initializes specialized Monte Carlo truth histograms for the task |
| 84 | + /// internal function called by init only in case of Monte Carlo truth |
| 85 | + /// \tparam T type of the xxis Object |
| 86 | + /// \param folderName Name of the directory in the output file (no suffix for reconstructed data/ Monte Carlo; "_MC" for Monte Carlo Truth) |
| 87 | + /// \param femtoObsAxis axis object for the femto observable axis |
| 88 | + template <typename T> |
| 89 | + void initMC(std::string /*folderName*/, std::string /*femtoObs*/, T /*femtoObsAxis*/, T /*multAxis*/, T /*mTAxis*/) |
| 90 | + { |
| 91 | + } |
| 92 | + |
| 93 | + /// Templated function to initialize the histograms for the task |
| 94 | + /// Always calls initBase to initialize the histograms for data/ Monte Carlo reconstructed |
| 95 | + /// In case of Monte Carlo, calls initBase again for Monte Carlo truth and the specialized function initMC for additional histogramms |
| 96 | + /// \tparam T type of the configurable for the axis configuration |
| 97 | + /// \param registry Histogram registry to be passed |
| 98 | + /// \param kstarBins k* binning for the histograms |
| 99 | + /// \param multBins multiplicity binning for the histograms |
| 100 | + /// \param kTBins kT binning for the histograms |
| 101 | + /// \param mTBins mT binning for the histograms |
| 102 | + /// \param etaBins eta binning for the histograms |
| 103 | + /// \param phiBins phi binning for the histograms |
| 104 | + /// \param isMC add Monte Carlo truth histograms to the output file |
| 105 | + template <typename T, typename P> |
| 106 | + void init(HistogramRegistry* registry, T& kstarBins, T& multBins, T& kTBins, T& mTBins, T& multBins3D, T& mTBins3D, P& etaBins, P& phiBins, bool isMC, bool use3dplots) |
| 107 | + { |
| 108 | + mHistogramRegistry = registry; |
| 109 | + std::string femtoObs; |
| 110 | + if constexpr (FemtoObs == femto_flow_angular_container::Observable::kstar) { |
| 111 | + femtoObs = "#it{k*} (GeV/#it{c})"; |
| 112 | + } |
| 113 | + |
| 114 | + std::vector<double> tmpVecMult = multBins; |
| 115 | + framework::AxisSpec multAxis = {tmpVecMult, "Multiplicity"}; |
| 116 | + framework::AxisSpec femtoObsAxis = {kstarBins, femtoObs.c_str()}; |
| 117 | + framework::AxisSpec kTAxis = {kTBins, "#it{k}_{T} (GeV/#it{c})"}; |
| 118 | + framework::AxisSpec mTAxis = {mTBins, "#it{m}_{T} (GeV/#it{c}^{2})"}; |
| 119 | + |
| 120 | + framework::AxisSpec multAxis3D = {multBins3D, "Multiplicity"}; |
| 121 | + framework::AxisSpec mTAxis3D = {mTBins3D, "#it{m}_{T} (GeV/#it{c})"}; |
| 122 | + |
| 123 | + // angular correlations |
| 124 | + mPhiLow = (-static_cast<int>(phiBins / 4) + 0.5) * o2::constants::math::TwoPI / phiBins; |
| 125 | + mPhiHigh = o2::constants::math::TwoPI + (-static_cast<int>(phiBins / 4) + 0.5) * o2::constants::math::TwoPI / phiBins; |
| 126 | + framework::AxisSpec phiAxis = {phiBins, mPhiLow, mPhiHigh}; |
| 127 | + framework::AxisSpec etaAxis = {etaBins, -2.0, 2.0}; |
| 128 | + |
| 129 | + std::string folderName = static_cast<std::string>(FolderSuffix[EventType]) + static_cast<std::string>(o2::aod::femtoflow_mc_particle::MCTypeName[o2::aod::femtoflow_mc_particle::MCType::kRecon]); |
| 130 | + |
| 131 | + initBase(folderName, femtoObs, femtoObsAxis, multAxis, kTAxis, mTAxis, multAxis3D, mTAxis3D, etaAxis, phiAxis, use3dplots); |
| 132 | + if (isMC) { |
| 133 | + folderName = static_cast<std::string>(FolderSuffix[EventType]) + static_cast<std::string>(o2::aod::femtoflow_mc_particle::MCTypeName[o2::aod::femtoflow_mc_particle::MCType::kTruth]); |
| 134 | + initBase(folderName, femtoObs, femtoObsAxis, multAxis, kTAxis, mTAxis, multAxis3D, mTAxis3D, etaAxis, phiAxis, use3dplots); |
| 135 | + initMC(folderName, femtoObs, femtoObsAxis, multAxis, mTAxis); |
| 136 | + } |
| 137 | + } |
| 138 | + |
| 139 | + /// Set the PDG codes of the two particles involved |
| 140 | + /// \param pdg1 PDG code of particle one |
| 141 | + /// \param pdg2 PDG code of particle two |
| 142 | + void setPDGCodes(const int pdg1, const int pdg2) |
| 143 | + { |
| 144 | + mMassOne = TDatabasePDG::Instance()->GetParticle(pdg1)->Mass(); |
| 145 | + mMassTwo = TDatabasePDG::Instance()->GetParticle(pdg2)->Mass(); |
| 146 | + mPDGOne = pdg1; |
| 147 | + mPDGTwo = pdg2; |
| 148 | + } |
| 149 | + |
| 150 | + /// Pass a pair to the container and compute all the relevant observables |
| 151 | + /// Called by setPair both in case of data/ and Monte Carlo reconstructed and for Monte Carlo truth |
| 152 | + /// \tparam T type of the femtoflowparticle |
| 153 | + /// \param part1 Particle one |
| 154 | + /// \param part2 Particle two |
| 155 | + /// \param mult Multiplicity of the event |
| 156 | + template <o2::aod::femtoflow_mc_particle::MCType mc, typename T> |
| 157 | + void setPairBase(const float /*femtoObs*/, const float /*mT*/, T const& part1, T const& part2, const int /*mult*/, bool use3dplots, float weight = 1.0f) |
| 158 | + { |
| 159 | + deltaEta = part1.eta() - part2.eta(); |
| 160 | + |
| 161 | + deltaPhi = part1.phi() - part2.phi(); |
| 162 | + |
| 163 | + while (deltaPhi < mPhiLow) { |
| 164 | + deltaPhi += o2::constants::math::TwoPI; |
| 165 | + } |
| 166 | + while (deltaPhi > mPhiHigh) { |
| 167 | + deltaPhi -= o2::constants::math::TwoPI; |
| 168 | + } |
| 169 | + |
| 170 | + mHistogramRegistry->fill(HIST(FolderSuffix[EventType]) + HIST(o2::aod::femtoflow_mc_particle::MCTypeName[mc]) + HIST("/DeltaEtaDeltaPhi"), deltaPhi, deltaEta, weight); |
| 171 | + if (use3dplots) { |
| 172 | + // use 3d plots |
| 173 | + } |
| 174 | + } |
| 175 | + |
| 176 | + /// Called by setPair only in case of Monte Carlo truth |
| 177 | + /// Fills MC truth specific histogramms: |
| 178 | + /// - kstar distribution plots with RECONSTRUCTED information but ONLY for non-fake candidates; needed for purity calculations of tracks |
| 179 | + /// - kstar resolution matrix |
| 180 | + /// Note: Standard histogramms with MC truth information are filled with the setPairBase function |
| 181 | + /// \param part1 Particle one |
| 182 | + /// \param part2 Particle two |
| 183 | + /// \param mult Multiplicity of the event |
| 184 | + void setPairMC(const float /*femtoObsMC*/, const float /*femtoObs*/, const float /*mT*/, const int /*mult*/) |
| 185 | + { |
| 186 | + if (mHistogramRegistry) { |
| 187 | + // Fill the kstar distributions with the reconstructed information but only for particles with the right PDG code |
| 188 | + } |
| 189 | + } |
| 190 | + |
| 191 | + /// Templated function to handle data/ Monte Carlo reconstructed and Monte Carlo truth |
| 192 | + /// Always calls setPairBase to compute the observables with reconstructed data |
| 193 | + /// In case of Monte Carlo, calls setPairBase with MC info and specialized function setPairMC for additional histogramms |
| 194 | + /// \tparam T type of the femtoflowparticle |
| 195 | + /// \param part1 Particle one |
| 196 | + /// \param part2 Particle two |
| 197 | + /// \param mult Multiplicity of the event |
| 198 | + template <bool isMC, typename T> |
| 199 | + void setPair(T const& part1, T const& part2, const int mult, bool use3dplots, float weight = 1.0f) |
| 200 | + { |
| 201 | + float femtoObs, femtoObsMC; |
| 202 | + // Calculate femto observable and the mT with reconstructed information |
| 203 | + if constexpr (FemtoObs == femto_flow_angular_container::Observable::kstar) { |
| 204 | + femtoObs = FemtoFlowMath::getkstar(part1, mMassOne, part2, mMassTwo); |
| 205 | + } |
| 206 | + const float mT = FemtoFlowMath::getmT(part1, mMassOne, part2, mMassTwo); |
| 207 | + |
| 208 | + if (mHistogramRegistry) { |
| 209 | + setPairBase<o2::aod::femtoflow_mc_particle::MCType::kRecon>(femtoObs, mT, part1, part2, mult, use3dplots, weight); |
| 210 | + |
| 211 | + if constexpr (isMC) { |
| 212 | + if (part1.has_fdMCParticle() && part2.has_fdMCParticle()) { |
| 213 | + // calculate the femto observable and the mT with MC truth information |
| 214 | + if constexpr (FemtoObs == femto_flow_angular_container::Observable::kstar) { |
| 215 | + femtoObsMC = FemtoFlowMath::getkstar(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); |
| 216 | + } |
| 217 | + const float mTMC = FemtoFlowMath::getmT(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); |
| 218 | + |
| 219 | + if (std::abs(part1.fdMCParticle().pdgMCTruth()) == std::abs(mPDGOne) && std::abs(part2.fdMCParticle().pdgMCTruth()) == std::abs(mPDGTwo)) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates |
| 220 | + setPairBase<o2::aod::femtoflow_mc_particle::MCType::kTruth>(femtoObsMC, mTMC, part1.fdMCParticle(), part2.fdMCParticle(), mult, use3dplots, weight); |
| 221 | + setPairMC(femtoObsMC, femtoObs, mT, mult); |
| 222 | + } else { |
| 223 | + } |
| 224 | + |
| 225 | + } else { |
| 226 | + } |
| 227 | + } |
| 228 | + } |
| 229 | + } |
| 230 | + |
| 231 | + protected: |
| 232 | + HistogramRegistry* mHistogramRegistry = nullptr; ///< For QA output |
| 233 | + static constexpr std::string_view FolderSuffix[2] = {"SameEvent", "MixedEvent"}; ///< Folder naming for the output according to EventType |
| 234 | + static constexpr femto_flow_angular_container::Observable FemtoObs = obs; ///< Femtoscopic observable to be computed (according to femto_flow_angular_container::Observable) |
| 235 | + static constexpr int EventType = eventType; ///< Type of the event (same/mixed, according to femto_flow_angular_container::EventType) |
| 236 | + float mMassOne = 0.f; ///< PDG mass of particle 1 |
| 237 | + float mMassTwo = 0.f; ///< PDG mass of particle 2 |
| 238 | + int mPDGOne = 0; ///< PDG code of particle 1 |
| 239 | + int mPDGTwo = 0; ///< PDG code of particle 2 |
| 240 | + double mPhiLow; |
| 241 | + double mPhiHigh; |
| 242 | + double deltaEta; |
| 243 | + double deltaPhi; |
| 244 | +}; |
| 245 | + |
| 246 | +} // namespace o2::analysis::femto_flow |
| 247 | + |
| 248 | +#endif // PWGCF_FEMTOFLOW_CORE_FEMTOFLOWANGULARCONTAINER_H_ |
0 commit comments