diff --git a/PWGCF/Femto/Core/pairCleaner.h b/PWGCF/Femto/Core/pairCleaner.h index 3bf2daf45c0..d7d303a31c6 100644 --- a/PWGCF/Femto/Core/pairCleaner.h +++ b/PWGCF/Femto/Core/pairCleaner.h @@ -29,11 +29,12 @@ class BasePairCleaner virtual ~BasePairCleaner() = default; template - void init(T const& pairCuts) + void init(T const& PairCuts) { if constexpr (modes::isFlagSet(mode, modes::Mode::kMc)) { - mMixPairsWithCommonAncestor = pairCuts.mixOnlyCommonAncestor.value; - mMixPairsWithNonCommonAncestor = pairCuts.mixOnlyNonCommonAncestor.value; + mMixPairsWithCommonAncestor = PairCuts.mixOnlyCommonAncestor.value; + mMixPairsWithNonCommonAncestor = PairCuts.mixOnlyNonCommonAncestor.value; + mUseMotherAsAncestor = PairCuts.useMotherAsAncestor.value; if (mMixPairsWithCommonAncestor && mMixPairsWithNonCommonAncestor) { LOG(fatal) << "Both mixing with common and non-common ancestor is activated. Breaking..."; } @@ -48,34 +49,31 @@ class BasePairCleaner }; // mc only + // ancestry is checked either with the partonic mother or with the last ancestor (i.e. the direct mother), depending on mUseMotherAsAncestor template - bool mcPairHasCommonAncestor(T1 const& particle1, T2 const& particle2, T3 const& /*partonicMothers*/) const + bool mcPairHasCommonAncestor(T1 const& particle1, T2 const& particle2, T3 const& partonicMothers) const { - // if one of the two particles has no associated partonic mother, we cannot know if they have a common anchestor, so we break out with false - if (!particle1.has_fMcPartMoth() || !particle2.has_fMcPartMoth()) { - return false; + if (mUseMotherAsAncestor) { + return this->mcPairHasCommonMother(particle1, particle2); } - - // get partonic mothers - auto partonicMother1 = particle1.template fMcPartMoth_as(); - auto partonicMother2 = particle2.template fMcPartMoth_as(); - - return partonicMother1.globalIndex() == partonicMother2.globalIndex(); + return this->mcPairHasCommonPartonicMother(particle1, particle2, partonicMothers); }; template - bool mcPairHasNonCommonAncestor(T1 const& particle1, T2 const& particle2, T3 const& /*partonicMothers*/) const + bool mcPairHasNonCommonAncestor(T1 const& particle1, T2 const& particle2, T3 const& partonicMothers) const { + if (mUseMotherAsAncestor) { + // if one of the two particles has no associated mother, we cannot know if they have a common anchestor, so we break out with false + if (!particle1.has_fMcMother() || !particle2.has_fMcMother()) { + return false; + } + return !this->mcPairHasCommonMother(particle1, particle2); + } // if one of the two particles has no associated partonic mother, we cannot know if they have a common anchestor, so we break out with false if (!particle1.has_fMcPartMoth() || !particle2.has_fMcPartMoth()) { return false; } - - // get partonic mothers - auto partonicMother1 = particle1.template fMcPartMoth_as(); - auto partonicMother2 = particle2.template fMcPartMoth_as(); - - return partonicMother1.globalIndex() != partonicMother2.globalIndex(); + return !this->mcPairHasCommonPartonicMother(particle1, particle2, partonicMothers); }; // reco + mc @@ -111,6 +109,38 @@ class BasePairCleaner bool mMixPairsWithCommonAncestor = false; bool mMixPairsWithNonCommonAncestor = false; + + private: + // require both particles to originate from the same partonic mother + template + bool mcPairHasCommonPartonicMother(T1 const& particle1, T2 const& particle2, T3 const& /*partonicMothers*/) const + { + // if one of the two particles has no associated partonic mother, we cannot know if they have a common anchestor, so we break out with false + if (!particle1.has_fMcPartMoth() || !particle2.has_fMcPartMoth()) { + return false; + } + + // get partonic mothers + auto partonicMother1 = particle1.template fMcPartMoth_as(); + auto partonicMother2 = particle2.template fMcPartMoth_as(); + + return partonicMother1.globalIndex() == partonicMother2.globalIndex(); + }; + + // require both particles to have the same last ancestor, i.e. the same direct mother + // there is exactly one row in the mother table per generated mother, so comparing the indices is sufficient + template + bool mcPairHasCommonMother(T1 const& particle1, T2 const& particle2) const + { + // if one of the two particles has no associated mother, we cannot know if they have a common anchestor, so we break out with false + if (!particle1.has_fMcMother() || !particle2.has_fMcMother()) { + return false; + } + + return particle1.fMcMotherId() == particle2.fMcMotherId(); + }; + + bool mUseMotherAsAncestor = false; }; class TrackTrackPairCleaner : public BasePairCleaner @@ -147,14 +177,14 @@ class V0V0PairCleaner : public BasePairCleaner // also works for particles decay public: V0V0PairCleaner() = default; template - bool isCleanPair(T1 const& v01, T2 const& v02, T3 const& trackTable) const + bool isCleanPair(const T1& v01, const T2& v02, const T3& trackTable) const { auto posDaughter1 = trackTable.rawIteratorAt(v01.posDauId() - trackTable.offset()); auto negDaughter1 = trackTable.rawIteratorAt(v01.negDauId() - trackTable.offset()); auto posDaughter2 = trackTable.rawIteratorAt(v02.posDauId() - trackTable.offset()); auto negDaughter2 = trackTable.rawIteratorAt(v02.negDauId() - trackTable.offset()); - return this->isCleanParticlePair(v01, v02) && - this->isCleanParticlePair(posDaughter1, posDaughter2) && this->isCleanParticlePair(negDaughter1, negDaughter2) && + // check all charge combinations + return this->isCleanParticlePair(posDaughter1, posDaughter2) && this->isCleanParticlePair(negDaughter1, negDaughter2) && this->isCleanParticlePair(posDaughter1, negDaughter2) && this->isCleanParticlePair(negDaughter1, posDaughter2); } @@ -181,7 +211,7 @@ class TrackV0PairCleaner : public BasePairCleaner // also works for particles de public: TrackV0PairCleaner() = default; template - bool isCleanPair(T1 const& track, T2 const& v0, T3 const& trackTable) const + bool isCleanPair(const T1& track, const T2& v0, const T3& trackTable) const { auto posDaughter = trackTable.rawIteratorAt(v0.posDauId() - trackTable.offset()); auto negDaughter = trackTable.rawIteratorAt(v0.negDauId() - trackTable.offset()); @@ -211,7 +241,7 @@ class TrackKinkPairCleaner : public BasePairCleaner public: TrackKinkPairCleaner() = default; template - bool isCleanPair(T1 const& track, T2 const& kink, T3 const& trackTable) const + bool isCleanPair(const T1& track, const T2& kink, const T3& trackTable) const { auto chaDaughter = trackTable.rawIteratorAt(kink.chaDauId() - trackTable.offset()); return this->isCleanParticlePair(chaDaughter, track); @@ -240,7 +270,7 @@ class TrackCascadePairCleaner : public BasePairCleaner public: TrackCascadePairCleaner() = default; template - bool isCleanPair(T1 const& track, T2 const& cascade, T3 const& trackTable) const + bool isCleanPair(const T1& track, const T2& cascade, const T3& trackTable) const { auto bachelor = trackTable.rawIteratorAt(cascade.bachelorId() - trackTable.offset()); auto posDaughter = trackTable.rawIteratorAt(cascade.posDauId() - trackTable.offset()); diff --git a/PWGCF/Femto/Core/pairHistManager.h b/PWGCF/Femto/Core/pairHistManager.h index 99d66198ad7..5f2dd426519 100644 --- a/PWGCF/Femto/Core/pairHistManager.h +++ b/PWGCF/Femto/Core/pairHistManager.h @@ -69,8 +69,6 @@ enum PairHist { kKstarVsMt, kKstarVsMult, kKstarVsCent, - // 3D: k* vs kT vs centrality - kKstarVsKtVsCent, // 2D with mass kKstarVsMass1, kKstarVsMass2, @@ -186,7 +184,6 @@ struct ConfPairBinning : o2::framework::ConfigurableGroup { o2::framework::Configurable usePdgMass{"usePdgMass", true, "(Reco) Use PDF masses for 4-vectors. If false, use reconstructed mass (if available). Not consulted for pure mc-truth pairs, which always use PDG mass"}; o2::framework::Configurable plot1D{"plot1D", true, "(Reco/Mc) Enable 1D histograms"}; o2::framework::Configurable plot2D{"plot2D", true, "(Reco/Mc) Enable 2D histograms"}; - o2::framework::Configurable plotKstarVsKtVsCent{"plotKstarVsKtVsCent", false, "(Reco/Mc) Enable 3D histogram (Kstar Vs Kt Vs Cent)"}; o2::framework::Configurable plotKstarVsMtVsMult{"plotKstarVsMtVsMult", false, "(Reco/Mc) Enable 3D histogram (Kstar Vs Mt Vs Mult)"}; o2::framework::Configurable plotKstarVsMtVsMultVsCent{"plotKstarVsMtVsMultVsCent", false, "(Reco/Mc) Enable 4D histogram (Kstar Vs Mt Vs Mult Vs Cent)"}; o2::framework::Configurable plotKstarVsMtVsPt1VsPt2{"plotKstarVsMtVsPt1VsPt2", false, "(Reco/Mc) Enable 4D histogram (Kstar Vs Mt Vs Pt1 Vs Pt2)"}; @@ -216,7 +213,7 @@ struct ConfPairBinning : o2::framework::ConfigurableGroup { o2::framework::ConfigurableAxis pt2{"pt2", {{100, 0, 6}}, "Pt binning for particle 2"}; o2::framework::ConfigurableAxis mass1{"mass1", {{100, 0, 2}}, "Mass binning for particle 1 (if particle has mass getter, otherwise PDG mass)"}; o2::framework::ConfigurableAxis mass2{"mass2", {{100, 0, 2}}, "Mass binning for particle 2 (if particle has mass getter, otherwise PDG mass)"}; - o2::framework::ConfigurableAxis massInv{"massInv", {{100, 0, 5}}, "Invariant Mass binning"}; + o2::framework::ConfigurableAxis massInv{"massInv", {{100, 0, 2}}, "Invariant Mass binning"}; o2::framework::ConfigurableAxis dalitzMtot{"dalitzMtot", {{100, 0, 10}}, "Total invariant mass squared binning in darlitz plot"}; o2::framework::ConfigurableAxis dalitzM12{"dalitzM12", {{100, 0, 10}}, "Mass12 binning of darlitz plot"}; o2::framework::ConfigurableAxis dalitzM13{"dalitzM13", {{100, 0, 10}}, "Mass13 binning of darlitz plot"}; @@ -234,7 +231,7 @@ struct ConfPairBinning : o2::framework::ConfigurableGroup { o2::framework::Configurable shUseCent{"shUseCent", false, "SH: bin by centrality instead of multiplicity"}; o2::framework::ConfigurableAxis shCentBins{"shCentBins", {o2::framework::VARIABLE_WIDTH, 0.0f, 200.0f}, "SH: multiplicity/centrality bin edges (like FemtoUniverse confMultKstarBins)"}; o2::framework::ConfigurableAxis shKtBins{"shKtBins", {o2::framework::VARIABLE_WIDTH, 0.1f, 0.2f, 0.3f, 0.4f}, "SH: kT bin edges (like FemtoUniverse confKtKstarBins)"}; - o2::framework::Configurable shPlot1D{"shPlot1D", false, "(SH) Also fill the 1D qinv/k* distribution (h1D) and the bin occupancy (BinCount) per (mult,kT) bin"}; + o2::framework::Configurable shPlot1D{"shPlot1D", false, "(SH) Also fill 1D qinv/k* numerator/denominator (h1D) per (mult,kT) bin"}; }; struct ConfPairCuts : o2::framework::ConfigurableGroup { @@ -249,6 +246,7 @@ struct ConfPairCuts : o2::framework::ConfigurableGroup { o2::framework::Configurable massInvMax{"massInvMax", -1, "Maximal invariant mass (set to -1 to deactivate)"}; o2::framework::Configurable mixOnlyCommonAncestor{"mixOnlyCommonAncestor", false, "Require pair to have common anchestor (in the same event)"}; o2::framework::Configurable mixOnlyNonCommonAncestor{"mixOnlyNonCommonAncestor", false, "Require pair to have non-common anchestor (in the same event)"}; + o2::framework::Configurable useMotherAsAncestor{"useMotherAsAncestor", false, "Use the first ancestor (i.e. the direct mother) instead of the partonic mother when requiring (non-)common ancestry"}; }; // the enum gives the correct index in the array @@ -280,7 +278,6 @@ constexpr std::array, kPairHistogramLast> {kPt1VsMinv, o2::framework::HistType::kTH2F, "hPt1VsMinv", "p_{T,1} vs m_{Inv}; p_{T,1} (GeV/#it{c}); m_{Inv} (GeV/#it{c}^{2})"}, {kPt2VsMinv, o2::framework::HistType::kTH2F, "hPt2VsMinv", "p_{T,2} vs m_{Inv}; p_{T,2} (GeV/#it{c}); m_{Inv} (GeV/#it{c}^{2})"}, // n-D - {kKstarVsKtVsCent, o2::framework::HistType::kTHnSparseF, "hKstarVsKtVsCent", "k* vs k_{T} vs centrality; k* (GeV/#it{c}); k_{T} (GeV/#it{c}); Centrality (%);"}, {kKstarVsMtVsMult, o2::framework::HistType::kTHnSparseF, "hKstarVsMtVsMult", "k* vs m_{T} vs multiplicity; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); Multiplicity;"}, {kKstarVsMtVsMultVsCent, o2::framework::HistType::kTHnSparseF, "hKstarVsMtVsMultVsCent", "k* vs m_{T} vs multiplicity vs centrality; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); Multiplicity; Centrality (%);"}, // n-D with pt @@ -371,7 +368,6 @@ constexpr std::array, kPairHistogramLast> {kKstarVsMt, {(confAnalysis).kstar, (confAnalysis).mt}}, \ {kKstarVsMult, {(confAnalysis).kstar, (confAnalysis).multiplicity}}, \ {kKstarVsCent, {(confAnalysis).kstar, (confAnalysis).centrality}}, \ - {kKstarVsKtVsCent, {(confAnalysis).kstar, (confAnalysis).kt, (confAnalysis).centrality}}, \ {kKstarVsMass1, {(confAnalysis).kstar, (confAnalysis).mass1}}, \ {kKstarVsMass2, {(confAnalysis).kstar, (confAnalysis).mass2}}, \ {kMass1VsMass2, {(confAnalysis).mass1, (confAnalysis).mass2}}, \ @@ -496,11 +492,6 @@ constexpr char PrefixTrackTrackMe[] = "TrackTrack/ME/"; constexpr char PrefixTrackV0Se[] = "TrackV0/SE/"; constexpr char PrefixTrackV0Me[] = "TrackV0/ME/"; -constexpr char PrefixTrackD0Se[] = "TrackD0/SE/"; -constexpr char PrefixTrackD0Me[] = "TrackD0/ME/"; -constexpr char PrefixD0D0Se[] = "D0D0/SE/"; -constexpr char PrefixD0D0Me[] = "D0D0/ME/"; - constexpr char PrefixV0V0Se[] = "V0V0/SE/"; constexpr char PrefixV0V0Me[] = "V0V0/ME/"; @@ -546,7 +537,6 @@ class PairHistManager // flags for histograms mPlot1d = ConfPairBinning.plot1D.value; mPlot2d = ConfPairBinning.plot2D.value; - mPlotKstarVsKtVsCent = ConfPairBinning.plotKstarVsKtVsCent.value; mPlotKstarVsMtVsMult = ConfPairBinning.plotKstarVsMtVsMult.value; mPlotKstarVsMtVsMultVsCent = ConfPairBinning.plotKstarVsMtVsMultVsCent.value; @@ -586,8 +576,6 @@ class PairHistManager // copy bin edges, stripping the leading VARIABLE_WIDTH (0) marker mShCentEdges.assign(ConfPairBinning.shCentBins.value.begin() + 1, ConfPairBinning.shCentBins.value.end()); mShKtEdges.assign(ConfPairBinning.shKtBins.value.begin() + 1, ConfPairBinning.shKtBins.value.end()); - mShCentSpec = {ConfPairBinning.shCentBins, mShUseCent ? "centrality (%)" : "multiplicity"}; - mShKtSpec = {ConfPairBinning.shKtBins, "k_{T} (GeV/#it{c})"}; } // transverse mass type @@ -709,9 +697,7 @@ class PairHistManager } if (mPlotDalitz) { - if constexpr (modes::isEqual(particleType1, modes::Particle::kTrack) && (modes::isEqual(particleType2, modes::Particle::kV0) || - modes::isEqual(particleType2, modes::Particle::kTwoTrackResonance) || - modes::isEqual(particleType2, modes::Particle::kCharmHadron))) { + if constexpr (modes::isEqual(particleType1, modes::Particle::kTrack) && modes::isEqual(particleType2, modes::Particle::kV0)) { auto posDaughter = trackTable.rawIteratorAt(particle2.posDauId() - trackTable.offset()); auto negDaughter = trackTable.rawIteratorAt(particle2.negDauId() - trackTable.offset()); ROOT::Math::PtEtaPhiMVector posDau4v = ROOT::Math::PtEtaPhiMVector(posDaughter.pt(), posDaughter.eta(), posDaughter.phi(), mPdgMassPosDau2); @@ -951,9 +937,6 @@ class PairHistManager } // higher dimensional histograms - if (mPlotKstarVsKtVsCent) { - mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsKtVsCent, HistTable), getHistDesc(kKstarVsKtVsCent, HistTable), getHistType(kKstarVsKtVsCent, HistTable), {Specs.at(kKstarVsKtVsCent)}); - } if (mPlotKstarVsMtVsMult) { mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMtVsMult, HistTable), getHistDesc(kKstarVsMtVsMult, HistTable), getHistType(kKstarVsMtVsMult, HistTable), {Specs.at(kKstarVsMtVsMult)}); } @@ -1031,80 +1014,80 @@ class PairHistManager const int nKt = static_cast(mShKtEdges.size()) - 1; mShYlmBuffer.assign(nJM, {}); - mShReal.resize(nJM); - mShImag.resize(nJM); + mShReal.resize(nCent); + mShImag.resize(nCent); mShCov.resize(nCent); mSh1D.resize(nCent); mShBinCount.resize(nCent); - - const std::string dir = std::string(prefix) + std::string(AnalysisDir) + "SH/"; - int ihist = 0; - for (int l = 0; l <= mShLMax; ++l) { - for (int m = -l; m <= l; ++m) { - std::string lm = std::to_string(l); - lm += (m < 0) ? std::to_string(l - m) : std::to_string(m); - std::string nameRe = dir; - nameRe += "ReYlm"; - nameRe += lm; - std::string nameIm = dir; - nameIm += "ImYlm"; - nameIm += lm; - // shared "Y_{l}^{m}" suffix for both titles - std::string ylmLabel = "Y_{"; - ylmLabel += std::to_string(l); - ylmLabel += "}^{"; - ylmLabel += std::to_string(m); - ylmLabel += "}"; - std::string titleRe = "Re "; - titleRe += ylmLabel; - titleRe += "; k* (GeV/#it{c}); mult/cent; k_{T} (GeV/#it{c})"; - std::string titleIm = "Im "; - titleIm += ylmLabel; - titleIm += "; k* (GeV/#it{c}); mult/cent; k_{T} (GeV/#it{c})"; - mShReal[ihist] = mHistogramRegistry->add(nameRe.c_str(), titleRe.c_str(), o2::framework::kTH3D, {mShKstarSpec, mShCentSpec, mShKtSpec}); - mShImag[ihist] = mHistogramRegistry->add(nameIm.c_str(), titleIm.c_str(), o2::framework::kTH3D, {mShKstarSpec, mShCentSpec, mShKtSpec}); - mShReal[ihist]->Sumw2(); - mShImag[ihist]->Sumw2(); - ++ihist; - } - } - - const int nAxisLM = 2 * nJM; - const o2::framework::AxisSpec covLmAxis{nAxisLM, -0.5, static_cast(nAxisLM) - 0.5, "l,m #times (re,im)"}; - for (int iCent = 0; iCent < nCent; ++iCent) { + mShReal[iCent].resize(nKt); + mShImag[iCent].resize(nKt); mShCov[iCent].resize(nKt); mSh1D[iCent].resize(nKt); mShBinCount[iCent].resize(nKt); - // name suffix: mult_{low}_{high} - std::string centSuffix = "_mult_"; - centSuffix += std::to_string(static_cast(mShCentEdges[iCent])); - centSuffix += "_"; - centSuffix += std::to_string(static_cast(mShCentEdges[iCent + 1])); + // folder name: mult_{low}_{high} + const std::string centFolder = "mult_" + std::to_string(static_cast(mShCentEdges[iCent])) + + "_" + std::to_string(static_cast(mShCentEdges[iCent + 1])); for (int iKt = 0; iKt < nKt; ++iKt) { - // name suffix: _mult_{low}_{high}_kT_{low*100}_{high*100} - std::string cellSuffix = centSuffix; - cellSuffix += "_kT_"; - cellSuffix += std::to_string(static_cast(mShKtEdges[iKt] * 100.0)); - cellSuffix += "_"; - cellSuffix += std::to_string(static_cast(mShKtEdges[iKt + 1] * 100.0)); + mShReal[iCent][iKt].resize(nJM); + mShImag[iCent][iKt].resize(nJM); + // folder name: kT_{low*100}_{high*100} + std::string ktFolder = "kT_"; + ktFolder += std::to_string(static_cast(mShKtEdges[iKt] * 100.0)); + ktFolder += "_"; + ktFolder += std::to_string(static_cast(mShKtEdges[iKt + 1] * 100.0)); + std::string dir = std::string(prefix) + std::string(AnalysisDir) + "SH/"; + dir += centFolder; + dir += "/"; + dir += ktFolder; + dir += "/"; + + int ihist = 0; + for (int l = 0; l <= mShLMax; ++l) { + for (int m = -l; m <= l; ++m) { + std::string lm = std::to_string(l); + lm += (m < 0) ? std::to_string(l - m) : std::to_string(m); + std::string nameRe = dir; + nameRe += "ReYlm"; + nameRe += lm; + std::string nameIm = dir; + nameIm += "ImYlm"; + nameIm += lm; + // shared "Y_{l}^{m}" suffix for both titles + std::string ylmLabel = "Y_{"; + ylmLabel += std::to_string(l); + ylmLabel += "}^{"; + ylmLabel += std::to_string(m); + ylmLabel += "}"; + std::string titleRe = "Re "; + titleRe += ylmLabel; + titleRe += "; k* (GeV/#it{c}); Re[A_{l}^{m}]"; + std::string titleIm = "Im "; + titleIm += ylmLabel; + titleIm += "; k* (GeV/#it{c}); Im[A_{l}^{m}]"; + mShReal[iCent][iKt][ihist] = mHistogramRegistry->add(nameRe.c_str(), titleRe.c_str(), o2::framework::kTH1D, {mShKstarSpec}); + mShImag[iCent][iKt][ihist] = mHistogramRegistry->add(nameIm.c_str(), titleIm.c_str(), o2::framework::kTH1D, {mShKstarSpec}); + mShReal[iCent][iKt][ihist]->Sumw2(); + mShImag[iCent][iKt][ihist]->Sumw2(); + ++ihist; + } + } // SH covariance TH3D + const int nAxisLM = 2 * nJM; + const o2::framework::AxisSpec covLmAxis{nAxisLM, -0.5, static_cast(nAxisLM) - 0.5, "l,m #times (re,im)"}; std::string nameCov = dir; nameCov += "Cov"; - nameCov += cellSuffix; mShCov[iCent][iKt] = mHistogramRegistry->add(nameCov.c_str(), "SH covariance; k* (GeV/#it{c}); l,m; l,m", o2::framework::kTH3D, {mShKstarSpec, covLmAxis, covLmAxis}); mShCov[iCent][iKt]->Sumw2(); - if (mShPlot1D) { - std::string nameBinCount = dir; - nameBinCount += "BinCount"; - nameBinCount += cellSuffix; - mShBinCount[iCent][iKt] = mHistogramRegistry->add(nameBinCount.c_str(), "SH bin occupancy; k* (GeV/#it{c}); Entries", o2::framework::kTH1D, {mShKstarSpec}); + std::string nameBinCount = dir; + nameBinCount += "BinCount"; + mShBinCount[iCent][iKt] = mHistogramRegistry->add(nameBinCount.c_str(), "SH bin occupancy; k* (GeV/#it{c}); Entries", o2::framework::kTH1D, {mShKstarSpec}); + if (mShPlot1D) { std::string name1D = dir; name1D += "h1D"; - name1D += cellSuffix; mSh1D[iCent][iKt] = mHistogramRegistry->add(name1D.c_str(), "1D distribution; k* (GeV/#it{c}); Entries", o2::framework::kTH1D, {mShKstarSpec}); mSh1D[iCent][iKt]->Sumw2(); } @@ -1236,9 +1219,6 @@ class PairHistManager // n-D histograms are only filled if enabled // if "mass" getter does not exist for particle, it will be just set to 0 // the user has to make sure that in this case the bin number of this dimension is set to 1 - if (mPlotKstarVsKtVsCent) { - mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsKtVsCent, HistTable)), mKstar, mKt, mCent); - } if (mPlotKstarVsMtVsMult) { mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMtVsMult, HistTable)), mKstar, mMt, mMult); } @@ -1306,14 +1286,13 @@ class PairHistManager mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kQoutQsideQlong, HistTable)), mQout, mQside, mQlong); } if (mPlotSH) { - const float shCentValue = mShUseCent ? mCent : mMult; - const int iCent = findShBin(shCentValue, mShCentEdges); + const int iCent = findShBin(mShUseCent ? mCent : mMult, mShCentEdges); const int iKt = findShBin(mKt, mShKtEdges); if (iCent >= 0 && iKt >= 0) { mYlm.doYlmUpToL(mShLMax, mShOut, mShSide, mShLong, mShYlmBuffer.data()); for (std::size_t i = 0; i < mShYlmBuffer.size(); ++i) { - mShReal[i]->Fill(mShKv, shCentValue, mKt, std::real(mShYlmBuffer[i])); - mShImag[i]->Fill(mShKv, shCentValue, mKt, -std::imag(mShYlmBuffer[i])); + mShReal[iCent][iKt][i]->Fill(mShKv, std::real(mShYlmBuffer[i])); + mShImag[iCent][iKt][i]->Fill(mShKv, -std::imag(mShYlmBuffer[i])); } // covariance: outer product of the (re, -im) Ylm vector packed on 2*nJM axes // (each Ylm contributes two consecutive axis bins: even = real, odd = -imag) @@ -1327,8 +1306,8 @@ class PairHistManager } } + mShBinCount[iCent][iKt]->Fill(mShKv, 1.0); if (mShPlot1D) { - mShBinCount[iCent][iKt]->Fill(mShKv, 1.0); // FemtoUniverse h1D = f3d[0]: qinv (=2k*) for identical-LCMS, else k*. const float sh1DValue = (mShFrame == ShFrameLcmsIdentical) ? (2.0f * mKstar) : mKstar; mSh1D[iCent][iKt]->Fill(sh1DValue); @@ -1649,7 +1628,6 @@ class PairHistManager bool mPlot1d = true; bool mPlot2d = true; - bool mPlotKstarVsKtVsCent = false; bool mPlotKstarVsMtVsMult = false; bool mPlotKstarVsMtVsMultVsCent = false; @@ -1696,8 +1674,6 @@ class PairHistManager static constexpr int ShFramePrf = 2; o2::framework::AxisSpec mShKstarSpec{{60, 0.0f, 0.3f}, "k* (GeV/#it{c})"}; // set in init() - o2::framework::AxisSpec mShCentSpec{{1, 0.0f, 200.0f}, "mult/cent"}; - o2::framework::AxisSpec mShKtSpec{{3, 0.1f, 0.4f}, "k_{T} (GeV/#it{c})"}; // kinematics computed in setPair(): axis value + 3 components feeding Ylm float mShKv = 0.f; // kstar (non-identical) or qinv (identical) @@ -1705,9 +1681,9 @@ class PairHistManager float mShSide = 0.f; float mShLong = 0.f; - // SH histograms per [ihist] (ihist = l*(l+1)+m); TH3: k* on X, mult/cent on Y, kT on Z - std::vector> mShReal; - std::vector> mShImag; + // SH histograms binned in [iCent][iKt][ihist]; ihist = l*(l+1)+m + std::vector>>> mShReal; + std::vector>>> mShImag; // SH covariance matrix per [iCent][iKt]; TH3d: k* on X, 2*nJM (l,m x re/im) std::vector>> mShCov; bool mShPlot1D = false; diff --git a/PWGCF/Femto/Core/tripletHistManager.h b/PWGCF/Femto/Core/tripletHistManager.h index b336170d838..601f6bf9fc4 100644 --- a/PWGCF/Femto/Core/tripletHistManager.h +++ b/PWGCF/Femto/Core/tripletHistManager.h @@ -140,6 +140,7 @@ struct ConfTripletCuts : o2::framework::ConfigurableGroup { o2::framework::Configurable mtMin{"mtMin", -1, "Minimal mt (set to -1 to deactivate)"}; o2::framework::Configurable mixOnlyCommonAncestor{"mixOnlyCommonAncestor", false, "Require pair to have common anchestor (in the same event)"}; o2::framework::Configurable mixOnlyNonCommonAncestor{"mixOnlyNonCommonAncestor", false, "Require pair to have non-common anchestor (in the same event)"}; + o2::framework::Configurable useMotherAsAncestor{"useMotherAsAncestor", false, "Use the first ancestor (i.e. the direct mother) instead of the partonic mother when requiring (non-)common ancestry"}; }; // the enum gives the correct index in the array