diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseSoftPionRemoval.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseSoftPionRemoval.h new file mode 100644 index 00000000000..ac374c05074 --- /dev/null +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseSoftPionRemoval.h @@ -0,0 +1,120 @@ +// Copyright 2019-2022 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file FemtoUniverseSoftPionRemoval.h +/// \brief FemtoUniverseSoftPionRemoval - Checking the soft pions from D* decay and removing them +/// \author Katarzyna Gwiździel, WUT, katarzyna.gwizdziel@cern.ch + +#ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSESOFTPIONREMOVAL_H_ +#define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSESOFTPIONREMOVAL_H_ + +#include + +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "Framework/HistogramRegistry.h" + +namespace o2::analysis::femto_universe +{ + +/// \class FemtoUniverseSoftPionRemoval +/// \brief Class taking care of removing soft pions from D* decays +/// \tparam partOne Type of particle 1 (Track/D0/...) +/// \tparam partTwo Type of particle 2 (Track/D0/...) +template +class FemtoUniverseSoftPionRemoval +{ + public: + /// Destructor + virtual ~FemtoUniverseSoftPionRemoval() = default; + + /// Initialization of the QA histograms + /// \param registry HistogramRegistry + void init(HistogramRegistry* registry) + { + if (registry) { + mHistogramRegistry = registry; + mHistogramRegistry->add("SoftPion/softPionMassVsPt", "; M(K#pi#pi-K#pi); p_{T}", kTH2F, {{200, 0.0, 0.2}, {36, 0., 36.}}); + } + } + + /// Check whether a track is a soft pion from D* decay + /// \tparam Part Data type of the particle + /// \tparam Parts Data type of the collection of all particles + /// \param part1 Particle 1 + /// \param part2 Particle 2 + /// \param particles Collection of all particles passed to the task + /// \return Whether the track is a soft pion + template + bool isSoftPion(Part const& part1, Part const& part2, Parts const& particles, bool isD0Cand, bool isD0barCand, double sigma) + { + if constexpr (kPartOneType == o2::aod::femtouniverseparticle::ParticleType::kTrack && kPartTwoType == o2::aod::femtouniverseparticle::ParticleType::kD0) { + /// Track-D0 combination part1 is hadron and part2 is D0 + if (part2.partType() != o2::aod::femtouniverseparticle::ParticleType::kD0) { + LOG(fatal) << "FemtoUniverseSoftPionRemoval: passed arguments don't agree with FemtoUniverseSoftPionRemoval instantiation! Please provide second argument kD0 candidate."; + return false; + } + // Getting D0 (part2) children + const auto& posChild = particles.iteratorAt(part2.index() - 2); + const auto& negChild = particles.iteratorAt(part2.index() - 1); + // Pion and kaon mass + double massPion = o2::constants::physics::MassPiPlus; + double massKaon = o2::constants::physics::MassKPlus; + // D* reconstruction + double pSum2 = std::pow(posChild.px() + negChild.px() + part1.px(), 2.0) + std::pow(posChild.py() + negChild.py() + part1.py(), 2.0) + std::pow(posChild.pz() + negChild.pz() + part1.pz(), 2.0); + // Energies of the daughters -> D0->K-pi+ + double e1Pi = std::sqrt(std::pow(massPion, 2.0) + std::pow(posChild.px(), 2.0) + std::pow(posChild.py(), 2.0) + std::pow(posChild.pz(), 2.0)); + double e1K = std::sqrt(std::pow(massKaon, 2.0) + std::pow(negChild.px(), 2.0) + std::pow(negChild.py(), 2.0) + std::pow(negChild.pz(), 2.0)); + // Energies of the daughters -> D0bar->K+pi- + double e2Pi = std::sqrt(std::pow(massPion, 2.0) + std::pow(negChild.px(), 2.0) + std::pow(negChild.py(), 2.0) + std::pow(negChild.pz(), 2.0)); + double e2K = std::sqrt(std::pow(massKaon, 2.0) + std::pow(posChild.px(), 2.0) + std::pow(posChild.py(), 2.0) + std::pow(posChild.pz(), 2.0)); + // Soft pion energy + auto ePion = RecoDecay::e(massPion, part1.p()); + // D* masses + double mDstar1 = std::sqrt(std::pow(e1Pi + e1K + ePion, 2.0) - pSum2); + double mDstar2 = std::sqrt(std::pow(e2Pi + e2K + ePion, 2.0) - pSum2); + + bool isSoftPion = false; + double softPiMass = 0.14542; // pion mass in D*->D0pi decay + double lowMassLimitSoftPion = softPiMass - 3.0 * sigma; + double highMassLimitSoftPion = softPiMass + 3.0 * sigma; + + if (isD0Cand) { + if (mDstar1 - part2.mLambda() > 0.) { + mHistogramRegistry->fill(HIST("SoftPion/softPionMassVsPt"), mDstar1 - part2.mLambda(), part2.pt()); + } + if ((std::abs(mDstar1 - part2.mLambda()) > lowMassLimitSoftPion) && (std::abs(mDstar1 - part2.mLambda()) < highMassLimitSoftPion)) { + isSoftPion = true; + } + } + + if (isD0barCand) { + if (mDstar2 - part2.mAntiLambda() > 0.) { + mHistogramRegistry->fill(HIST("SoftPion/softPionMassVsPt"), mDstar2 - part2.mAntiLambda(), part2.pt()); + } + if ((std::abs(mDstar2 - part2.mAntiLambda()) > lowMassLimitSoftPion) && (std::abs(mDstar2 - part2.mAntiLambda()) < highMassLimitSoftPion)) { + isSoftPion = true; + } + } + return isSoftPion; + } else { + LOG(fatal) << "FemtoUniverseSoftPionRemoval: Combination of objects not defined - quitting!"; + return false; + } + } + + private: + HistogramRegistry* mHistogramRegistry; ///< For QA output + static constexpr o2::aod::femtouniverseparticle::ParticleType kPartOneType = partOne; ///< Type of particle 1 + static constexpr o2::aod::femtouniverseparticle::ParticleType kPartTwoType = partTwo; ///< Type of particle 2 +}; +} // namespace o2::analysis::femto_universe + +#endif // PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSESOFTPIONREMOVAL_H_ diff --git a/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h b/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h index b5ceb44e2c8..eaebb852b97 100644 --- a/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h +++ b/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h @@ -105,11 +105,11 @@ DECLARE_SOA_DYNAMIC_COLUMN(Theta, theta, //! Compute the theta of the track }); DECLARE_SOA_DYNAMIC_COLUMN(Px, px, //! Compute the momentum in x in GeV/c [](float pt, float phi) -> float { - return pt * std::sin(phi); + return pt * std::cos(phi); }); DECLARE_SOA_DYNAMIC_COLUMN(Py, py, //! Compute the momentum in y in GeV/c [](float pt, float phi) -> float { - return pt * std::cos(phi); + return pt * std::sin(phi); }); DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, //! Compute the momentum in z in GeV/c [](float pt, float eta) -> float { @@ -123,7 +123,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(P, p, //! Compute the overall momentum in GeV/c DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! Sign of the track charge DECLARE_SOA_COLUMN(TpcNClsFound, tpcNClsFound, uint8_t); //! Number of TPC clusters DECLARE_SOA_COLUMN(TpcNClsCrossedRows, tpcNClsCrossedRows, uint8_t); //! Number of TPC crossed rows -DECLARE_SOA_COLUMN(TPCFractionSharedCls, tpcFractionSharedCls, float); //! Number of TPC crossed rows +DECLARE_SOA_COLUMN(TpcFractionSharedCls, tpcFractionSharedCls, float); //! Number of TPC crossed rows DECLARE_SOA_COLUMN(ItsNCls, itsNCls, uint8_t); //! Number of ITS clusters DECLARE_SOA_COLUMN(ItsNClsInnerBarrel, itsNClsInnerBarrel, uint8_t); //! Number of ITS clusters in the inner barrel //! TPC signal DECLARE_SOA_DYNAMIC_COLUMN(TpcCrossedRowsOverFindableCls, tpcCrossedRowsOverFindableCls, //! Compute the number of crossed rows over findable TPC clusters @@ -182,7 +182,7 @@ DECLARE_SOA_TABLE(FDExtParticles, "AOD", "FDEXTPARTICLE", track::TPCNClsFindable, femtouniverseparticle::TpcNClsCrossedRows, track::TPCNClsShared, - femtouniverseparticle::TPCFractionSharedCls, + femtouniverseparticle::TpcFractionSharedCls, track::TPCInnerParam, femtouniverseparticle::ItsNCls, femtouniverseparticle::ItsNClsInnerBarrel, @@ -260,6 +260,8 @@ enum ParticleOriginMCTruth { kFake, //! particle, that has NOT the PDG code of the current analysed particle kDaughterLambda, //! Daughter from a Lambda decay kDaughterSigmaplus, //! Daughter from a Sigma^plus decay + kPrompt, //! Orgin for D0/D0bar mesons + kNonPrompt, //! Orgin for D0/D0bar mesons kNOriginMCTruthTypes }; @@ -271,7 +273,9 @@ static constexpr std::string_view ParticleOriginMCTruthName[kNOriginMCTruthTypes "_NotPrimary", "_Fake", "_DaughterLambda", - "DaughterSigmaPlus"}; + "DaughterSigmaPlus", + "_Prompt", + "_NonPrompt"}; /// Distinguished between reconstructed and truth enum MCType { diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx index 6f74943d1e9..2f1a915cec4 100644 --- a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx @@ -144,6 +144,7 @@ struct FemtoUniverseProducerTask { Configurable confIsActivateCascade{"confIsActivateCascade", false, "Activate filling of Cascade into femtouniverse tables"}; Configurable confIsSelectCascOmega{"confIsSelectCascOmega", false, "Select Omegas for cascade analysis"}; Configurable confIsActivatePhi{"confIsActivatePhi", false, "Activate filling of Phi into femtouniverse tables"}; + Configurable confIsActiveD0{"confIsActiveD0", false, "Activate filling FU tables for D0/D0bar mesons"}; Configurable confMCTruthAnalysisWithPID{"confMCTruthAnalysisWithPID", true, "1: take only particles with specified PDG, 0: all particles (for MC Truth)"}; Configurable> confMCTruthPDGCodes{"confMCTruthPDGCodes", std::vector{211, -211, 2212, -2212, 333}, "PDG of particles to be stored"}; Configurable confCentFT0Min{"confCentFT0Min", 0.f, "Min CentFT0 value for centrality selection"}; @@ -307,8 +308,9 @@ struct FemtoUniverseProducerTask { struct : o2::framework::ConfigurableGroup { Configurable confD0D0barCandMaxY{"confD0D0barCandMaxY", -1., "max. cand. rapidity"}; Configurable confD0D0barCandEtaCut{"confD0D0barCandEtaCut", 0.8, "max. cand. pseudorapidity"}; + Configurable yD0D0barCandRecoMax{"yD0D0barCandRecoMax", 0.8, "MC Reco, max. rapidity of D0/D0bar cand."}; + Configurable yD0D0barCandGenMax{"yD0D0barCandGenMax", 0.8, "MC Truth, max. rapidity of D0/D0bar cand."}; Configurable storeD0D0barDoubleMassHypo{"storeD0D0barDoubleMassHypo", false, "Store D0/D0bar cand. which pass selection criteria for both, D0 and D0bar"}; - Configurable applyMLSelD0D0bar{"applyMLSelD0D0bar", false, "Use ML D0/D0bar selection"}; Configurable> classMlD0D0bar{"classMlD0D0bar", {0, 1, 2}, "Indexes of ML scores to be stored. Three indexes max."}; } ConfD0Selection; @@ -469,10 +471,10 @@ struct FemtoUniverseProducerTask { void init(InitContext&) { - if ((doprocessFullData || doprocessTrackPhiData || doprocessTrackData || doprocessTrackV0 || doprocessTrackCascadeData || doprocessTrackD0mesonData || doprocessTrackD0DataML || doprocessTrackCentRun2Data || doprocessTrackV0CentRun2Data || doprocessTrackCentRun3Data || doprocessV0CentRun3Data || doprocessCascadeCentRun3Data || doprocessTrackDataCentPP) == false && (doprocessFullMC || doprocessTrackMC || doprocessTrackMCTruth || doprocessTrackMCGen || doprocessTruthAndFullMCV0 || doprocessTruthAndFullMCCasc || doprocessFullMCCent || doprocessTrackCentRun3DataMC || doprocessTruthAndFullMCCentRun3) == false) { + if ((doprocessFullData || doprocessTrackPhiData || doprocessTrackData || doprocessTrackV0 || doprocessTrackCascadeData || doprocessTrackD0mesonData || doprocessTrackD0DataML || doprocessTrackCentRun2Data || doprocessTrackV0CentRun2Data || doprocessTrackCentRun3Data || doprocessV0CentRun3Data || doprocessCascadeCentRun3Data || doprocessTrackDataCentPP) == false && (doprocessFullMC || doprocessTrackMC || doprocessTrackMCTruth || doprocessTrackMCGen || doprocessTruthAndFullMCV0 || doprocessTrackD0MC || doprocessTruthAndFullMCCasc || doprocessFullMCCent || doprocessTrackCentRun3DataMC || doprocessTruthAndFullMCCentRun3) == false) { LOGF(fatal, "Neither processFullData nor processFullMC enabled. Please choose one."); } - if ((doprocessFullData || doprocessTrackPhiData || doprocessTrackData || doprocessTrackV0 || doprocessTrackCascadeData || doprocessTrackD0mesonData || doprocessTrackD0DataML || doprocessTrackCentRun2Data || doprocessTrackV0CentRun2Data || doprocessTrackCentRun3Data || doprocessV0CentRun3Data || doprocessCascadeCentRun3Data || doprocessTrackDataCentPP) == true && (doprocessFullMC || doprocessTrackMC || doprocessTrackMCTruth || doprocessTrackMCGen || doprocessTruthAndFullMCV0 || doprocessTruthAndFullMCCasc || doprocessFullMCCent || doprocessTrackCentRun3DataMC || doprocessTruthAndFullMCCentRun3) == true) { + if ((doprocessFullData || doprocessTrackPhiData || doprocessTrackData || doprocessTrackV0 || doprocessTrackCascadeData || doprocessTrackD0mesonData || doprocessTrackD0DataML || doprocessTrackCentRun2Data || doprocessTrackV0CentRun2Data || doprocessTrackCentRun3Data || doprocessV0CentRun3Data || doprocessCascadeCentRun3Data || doprocessTrackDataCentPP) == true && (doprocessFullMC || doprocessTrackMC || doprocessTrackMCTruth || doprocessTrackMCGen || doprocessTruthAndFullMCV0 || doprocessTrackD0MC || doprocessTruthAndFullMCCasc || doprocessFullMCCent || doprocessTrackCentRun3DataMC || doprocessTruthAndFullMCCentRun3) == true) { LOGF(fatal, "Cannot enable process Data and process MC at the same time. " "Please choose one."); @@ -673,7 +675,7 @@ struct FemtoUniverseProducerTask { -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., - -999.); // QA for phi or D0/D0bar + -999.); // QA for phi or D0/D0bar children } else if constexpr (isXi) { outputDebugParts(-999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., @@ -692,6 +694,35 @@ struct FemtoUniverseProducerTask { } } + template + void fillDebugD0D0barML(ParticleType const& particle) + { + if constexpr (isD0ML) { + outputDebugParts(-999., -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., + -999., -999., + particle.mlProbD0()[0], // getter decayVtxX + particle.mlProbD0()[1], // getter decayVtxY + particle.mlProbD0()[2], // getter decayVtxZ + -999.); // Additional info for D0/D0bar + } else if constexpr (isD0barML) { + outputDebugParts(-999., -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., + -999., -999., + particle.mlProbD0bar()[0], // getter decayVtxX + particle.mlProbD0bar()[1], // getter decayVtxY + particle.mlProbD0bar()[2], // getter decayVtxZ + -999.); // Additional info for D0/D0bar + } else { + outputDebugParts(-999., -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999.); + } + } + template void fillMCParticle(ParticleType const& particle, o2::aod::femtouniverseparticle::ParticleType fdparttype) { @@ -778,6 +809,44 @@ struct FemtoUniverseProducerTask { } } + template + void fillMCParticleD0(ParticleType const& hfCand) + { + if (std::abs(hfCand.flagMcMatchRec()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + // get corresponding MC particle and its info + int pdgCode = 0; + int hfCandOrigin = 99; + + if (hfCand.originMcRec() == RecoDecay::OriginType::Prompt) { + if (hfCand.isSelD0() == 1 && hfCand.isSelD0bar() == 0) { + hfCandOrigin = aod::femtouniverse_mc_particle::ParticleOriginMCTruth::kPrompt; + pdgCode = static_cast(Pdg::kD0); + } else if (hfCand.isSelD0() == 0 && hfCand.isSelD0bar() == 1) { + hfCandOrigin = aod::femtouniverse_mc_particle::ParticleOriginMCTruth::kPrompt; + pdgCode = static_cast(Pdg::kD0Bar); + } else { + hfCandOrigin = aod::femtouniverse_mc_particle::ParticleOriginMCTruth::kFake; + pdgCode = 0; + } + } else { + if (hfCand.isSelD0() == 1 && hfCand.isSelD0bar() == 0) { + hfCandOrigin = aod::femtouniverse_mc_particle::ParticleOriginMCTruth::kNonPrompt; + pdgCode = static_cast(Pdg::kD0); + } else if (hfCand.isSelD0() == 0 && hfCand.isSelD0bar() == 1) { + hfCandOrigin = aod::femtouniverse_mc_particle::ParticleOriginMCTruth::kNonPrompt; + pdgCode = static_cast(Pdg::kD0Bar); + } else { + hfCandOrigin = aod::femtouniverse_mc_particle::ParticleOriginMCTruth::kFake; + pdgCode = 0; + } + } + outputPartsMC(hfCandOrigin, pdgCode, hfCand.pt(), hfHelper.yD0(hfCand), hfCand.phi()); + outputPartsMCLabels(outputPartsMC.lastIndex()); + } else { + outputPartsMCLabels(-1); + } + } + template bool fillCollisions(CollisionType const& col, TrackType const& tracks) { @@ -1370,8 +1439,8 @@ struct FemtoUniverseProducerTask { double invMassD0 = 0.0; double invMassD0bar = 0.0; bool isD0D0bar = false; - std::vector outputMlD0D0bar = {-1., -1., -1.}; // this vector keeps the probabilities from the ML model for D0/D0bar - uint8_t daughFlag = 0; // flag = 0 (daugh of D0 or D0bar), 1 (daug of D0), -1 (daugh of D0bar) + double mlProbD0D0barBg = 0.0; + uint8_t daughFlag = 0; // flag = 0 (daugh of D0 or D0bar), 1 (daug of D0), -1 (daugh of D0bar) for (const auto& hfCand : hfCands) { @@ -1399,21 +1468,13 @@ struct FemtoUniverseProducerTask { if (hfCand.isSelD0() == 1 && hfCand.isSelD0bar() == 0) { invMassD0 = hfHelper.invMassD0ToPiK(hfCand); invMassD0bar = -hfHelper.invMassD0barToKPi(hfCand); - if (ConfD0Selection.applyMLSelD0D0bar) { - for (unsigned int iClass = 0; iClass < ConfD0Selection.classMlD0D0bar->size(); iClass++) { - outputMlD0D0bar[iClass] = hfCand.mlProbD0()[ConfD0Selection.classMlD0D0bar->at(iClass)]; - } - } + mlProbD0D0barBg = hfCand.mlProbD0()[0]; isD0D0bar = true; daughFlag = 1; } else if (hfCand.isSelD0() == 0 && hfCand.isSelD0bar() == 1) { invMassD0 = -hfHelper.invMassD0ToPiK(hfCand); invMassD0bar = hfHelper.invMassD0barToKPi(hfCand); - if (ConfD0Selection.applyMLSelD0D0bar) { - for (unsigned int iClass = 0; iClass < ConfD0Selection.classMlD0D0bar->size(); iClass++) { - outputMlD0D0bar[iClass] = hfCand.mlProbD0bar()[ConfD0Selection.classMlD0D0bar->at(iClass)]; - } - } + mlProbD0D0barBg = hfCand.mlProbD0bar()[0]; isD0D0bar = true; daughFlag = -1; } else if (hfCand.isSelD0() == 1 && hfCand.isSelD0bar() == 1) { @@ -1477,9 +1538,9 @@ struct FemtoUniverseProducerTask { hfCand.eta(), hfCand.phi(), aod::femtouniverseparticle::ParticleType::kD0, - -999, // cut, CutContainerType - -999, // PID, CutContainerType - outputMlD0D0bar[0], // saving only the probaility for store class 1 - background + -999, // cut, CutContainerType + -999, // PID, CutContainerType + mlProbD0D0barBg, // saving the probability for ML score class 1 indexChildID, invMassD0, // D0 mass (mLambda) invMassD0bar); // D0bar mass (mAntiLambda) @@ -1487,10 +1548,16 @@ struct FemtoUniverseProducerTask { if (confIsDebug) { fillDebugParticle(postrack); // QA for positive daughter fillDebugParticle(negtrack); // QA for negative daughter - fillDebugParticle(hfCand); // QA for D0/D0bar + if (hfCand.isSelD0() == 1 && hfCand.isSelD0bar() == 0) { + fillDebugD0D0barML(hfCand); // QA for D0/D0bar + } else if (hfCand.isSelD0() == 0 && hfCand.isSelD0bar() == 1) { + fillDebugD0D0barML(hfCand); + } else { + fillDebugD0D0barML(hfCand); + } } if constexpr (isMC) { - fillMCParticle(hfCand, o2::aod::femtouniverseparticle::ParticleType::kD0); + fillMCParticleD0(hfCand); } } } @@ -1775,6 +1842,135 @@ struct FemtoUniverseProducerTask { } } + template + void fillMCTruthParticlesD0(TrackType const& tracks, std::optional>> recoMcIds = std::nullopt) + { + std::vector childIDs = {0, 0}; // these IDs are necessary to keep track of the children + std::vector tmpIDtrack; + + for (const auto& particle : tracks) { + /// if the most open selection criteria are not fulfilled there is no + /// point looking further at the track + + if (particle.eta() < -ConfFilterCuts.confEtaFilterCut || particle.eta() > ConfFilterCuts.confEtaFilterCut) + continue; + if (particle.pt() < ConfFilterCuts.confPtLowFilterCut || particle.pt() > ConfFilterCuts.confPtHighFilterCut) + continue; + + uint32_t pdgCode = static_cast(particle.pdgCode()); + + if (confMCTruthAnalysisWithPID) { + bool pass = false; + std::vector tmpPDGCodes = confMCTruthPDGCodes; // necessary due to some features of the Configurable + for (auto const& pdg : tmpPDGCodes) { + if (static_cast(pdg) == static_cast(pdgCode)) { + if (pdgCode == 333) { // && (recoMcIds && recoMcIds->get().contains(particle.globalIndex()))) { // ATTENTION: all Phi mesons are NOT primary particles + pass = true; + } else if (pdgCode == 421) { + pass = true; + } else { + if (particle.isPhysicalPrimary() || (confActivateSecondaries && recoMcIds && recoMcIds->get().contains(particle.globalIndex()))) + pass = true; + } + } + } + if (!pass) + continue; + } + + // now the table is filled + if constexpr (resolveDaughs) { + tmpIDtrack.push_back(particle.globalIndex()); + continue; + } + if (confIsActiveD0) { + + auto mcD0origin = aod::femtouniverseparticle::ParticleType::kMCTruthTrack; + float ptGenB = -1; + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (ConfD0Selection.yD0D0barCandGenMax >= 0. && std::abs(RecoDecay::y(particle.pVector(), o2::constants::physics::MassD0)) > ConfD0Selection.yD0D0barCandGenMax) { + continue; + } + mcD0origin = aod::femtouniverseparticle::ParticleType::kMCTruthTrack; + // WORK IN PROGRESS: If needed changed it to prompt and non-prompt + /*if (particle.originMcGen() == RecoDecay::OriginType::Prompt) { + mcD0origin = aod::femtouniverse_mc_particle::ParticleOriginMCTruth::kPrompt; + ptGenB = -1; + } else { + mcD0origin = aod::femtouniverse_mc_particle::ParticleOriginMCTruth::kNonPrompt; + ptGenB = particle.idxBhadMotherPart().pt(); + }*/ + outputParts(outputCollision.lastIndex(), + particle.pt(), + particle.eta(), + particle.phi(), + mcD0origin, + 0, + pdgCode, + pdgCode, + childIDs, + RecoDecay::y(particle.pVector(), o2::constants::physics::MassD0), + ptGenB); // pT of the B hadron (mother particle, only when non-prompt D0) + } + } else { + outputCascParts(outputCollision.lastIndex(), + particle.pt(), + particle.eta(), + particle.phi(), + aod::femtouniverseparticle::ParticleType::kMCTruthTrack, + 0, + pdgCode, + pdgCode, + childIDs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + } + if (confIsDebug) { + fillDebugParticle(particle); + } + + // Workaround to keep the FDParticles and MC label tables + // aligned, so that they can be joined in the task. + if constexpr (transientLabels) { + outputPartsMCLabels(-1); + } + } + if constexpr (resolveDaughs) { + childIDs[0] = 0; + childIDs[1] = 0; + for (std::size_t i = 0; i < tmpIDtrack.size(); i++) { + const auto& particle = tracks.iteratorAt(tmpIDtrack[i] - tracks.begin().globalIndex()); + for (int daughIndex = 0, n = std::min(2ul, particle.daughtersIds().size()); daughIndex < n; daughIndex++) { + // loop to find the corresponding index of the daughters + for (std::size_t j = 0; j < tmpIDtrack.size(); j++) { + if (tmpIDtrack[j] == particle.daughtersIds()[daughIndex]) { + childIDs[daughIndex] = i - j; + break; + } + } + } + outputParts(outputCollision.lastIndex(), + particle.pt(), + particle.eta(), + particle.phi(), + aod::femtouniverseparticle::ParticleType::kMCTruthTrack, + 0, + static_cast(particle.pdgCode()), + particle.pdgCode(), + childIDs, + 0, + 0); + if (confIsDebug) { + fillDebugParticle(particle); + } + + // Workaround to keep the FDParticles and MC label tables + // aligned, so that they can be joined in the task. + if constexpr (transientLabels) { + outputPartsMCLabels(-1); + } + } + } + } + template void fillCollisionsAndTracksAndV0AndPhi(CollisionType const& col, TrackType const& tracks, V0Type const& fullV0s) @@ -1895,23 +2091,6 @@ struct FemtoUniverseProducerTask { } PROCESS_SWITCH(FemtoUniverseProducerTask, processTrackPhiMC, "Provide MC data for track Phi analysis", false); - void processTrackD0MC(aod::FemtoFullCollisionMC const& col, - aod::BCsWithTimestamps const&, - soa::Join const& tracks, - aod::McCollisions const&, - aod::McParticles const&) - { - // get magnetic field for run - getMagneticFieldTesla(col.bc_as()); - // fill the tables - const auto colcheck = fillCollisions(col, tracks); - if (colcheck) { - fillTracks(tracks); - // fillD0mesons(col, tracks, candidates); - } - } - PROCESS_SWITCH(FemtoUniverseProducerTask, processTrackD0MC, "Provide MC data for track D0 analysis", false); - void processTrackData(aod::FemtoFullCollision const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks) @@ -2028,7 +2207,9 @@ struct FemtoUniverseProducerTask { PresliceUnsorted> recoCollsPerMCColl = aod::mcparticle::mcCollisionId; PresliceUnsorted> recoCollsPerMCCollCentPbPb = aod::mcparticle::mcCollisionId; Preslice> perCollisionTracks = aod::track::collisionId; + template + void processTruthAndFullMC( aod::McCollisions const& mccols, aod::McParticles const& mcParticles, @@ -2135,6 +2316,43 @@ struct FemtoUniverseProducerTask { } PROCESS_SWITCH(FemtoUniverseProducerTask, processTruthAndFullMCCasc, "Provide both MC truth and reco for tracks and Cascades", false); + Preslice> perCollisionD0s = aod::track::collisionId; + void processTrackD0MC(aod::McCollisions const& mccols, + aod::TracksWMc const&, + soa::Join const& collisions, + soa::Filtered> const& tracks, + soa::Join const& hfMcGenCands, + soa::Join const& hfMcRecoCands, + aod::BCsWithTimestamps const&) + { + // MC Reco + std::set recoMcIds; + for (const auto& col : collisions) { + auto groupedTracks = tracks.sliceBy(perCollisionTracks, col.globalIndex()); + auto groupedD0s = hfMcRecoCands.sliceBy(perCollisionD0s, col.globalIndex()); + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + // fill the tables + const auto colcheck = fillCollisions(col, tracks); + if (colcheck) { + fillTracks(tracks); + fillD0D0barUsingML(col, groupedTracks, groupedD0s); + for (const auto& track : groupedTracks) { + if (trackCuts.isSelectedMinimal(track)) + recoMcIds.insert(track.mcParticleId()); + } + } + } + // MC Truth + for (const auto& mccol : mccols) { + auto groupedMCParticles = hfMcGenCands.sliceBy(perMCCollision, mccol.globalIndex()); + auto groupedCollisions = collisions.sliceBy(recoCollsPerMCColl, mccol.globalIndex()); + fillMCTruthCollisions(groupedCollisions, groupedMCParticles); // fills the reco collisions for mc collision + fillMCTruthParticlesD0(groupedMCParticles, recoMcIds); // fills mc particles + } + } + PROCESS_SWITCH(FemtoUniverseProducerTask, processTrackD0MC, "Provide MC data for track D0 analysis", false); + void processFullMCCent(aod::FemtoFullCollisionCentRun3 const& col, aod::BCsWithTimestamps const&, soa::Join const& tracks, diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx index 2eb3cd6eb74..234f2352971 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx @@ -39,6 +39,8 @@ #include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" #include "PWGCF/FemtoUniverse/Core/femtoUtils.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseSoftPionRemoval.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEfficiencyCalculator.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" @@ -47,19 +49,11 @@ using namespace o2; using namespace o2::analysis; using namespace o2::analysis::femto_universe; +using namespace o2::analysis::femto_universe::efficiency; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -namespace -{ -static constexpr int kNPart = 2; -static constexpr int kNCuts = 5; -static const std::vector partNames{"D0", "Track"}; -static const std::vector cutNames{"MaxPt", "PIDthr", "nSigmaTPC", "nSigmaTPCTOF", "MaxP"}; -static const float cutsTable[kNPart][kNCuts]{{4.05f, 1.f, 3.f, 3.f, 100.f}, {4.05f, 1.f, 3.f, 3.f, 100.f}}; -} // namespace - /// Returns deltaPhi value within the range [-pi/2, 3/2*pi] /// double getDeltaPhi(double phiD, double phiDbar) @@ -81,10 +75,15 @@ double wrapDeltaPhi0PI(double phiD, double phiDbar) struct FemtoUniversePairTaskTrackD0 { + Service pdgMC; + using FemtoFullParticles = soa::Join; SliceCache cache; Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + using FemtoMCParticles = soa::Join; + Preslice perColMC = aod::femtouniverseparticle::fdCollisionId; + /// Table for both particles struct : o2::framework::ConfigurableGroup { Configurable confNsigmaCombinedProton{"confNsigmaCombinedProton", 3.0, "TPC and TOF Proton Sigma (combined) for momentum > 0.5"}; @@ -92,8 +91,6 @@ struct FemtoUniversePairTaskTrackD0 { Configurable confNsigmaCombinedPion{"confNsigmaCombinedPion", 3.0, "TPC and TOF Pion Sigma (combined) for momentum > 0.5"}; Configurable confNsigmaTPCPion{"confNsigmaTPCPion", 3.0, "TPC Pion Sigma for momentum < 0.5"}; - Configurable> confCutTable{"confCutTable", {cutsTable[0], kNPart, kNCuts, partNames, cutNames}, "Particle selections"}; - Configurable confNspecies{"confNspecies", 2, "Number of particle spieces with PID info"}; Configurable confIsMC{"confIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; Configurable> confTrkPIDnSigmaMax{"confTrkPIDnSigmaMax", std::vector{4.f, 3.f, 2.f}, "This configurable needs to be the same as the one used in the producer task"}; Configurable confUse3D{"confUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; @@ -110,6 +107,8 @@ struct FemtoUniversePairTaskTrackD0 { Configurable confIsTrackIdentified{"confIsTrackIdentified", true, "Enable PID for the track"}; Configurable confTrackLowPtCut{"confTrackLowPtCut", 0.5, "Low pT cut of the track"}; Configurable confTrackHighPtCut{"confTrackHighPtCut", 2.5, "High pT cut of the track"}; + Configurable protonMinPtPidTpcTof{"protonMinPtPidTpcTof", 0.5, "Momentum threshold for change of the PID method (from using TPC to TPC and TOF)."}; + Configurable pionMinPtPidTpcTof{"pionMinPtPidTpcTof", 0.5, "Momentum threshold for change of the PID method (from using TPC to TPC and TOF)."}; } ConfTrack; /// Particle 2 --- D0/D0bar meson @@ -118,39 +117,57 @@ struct FemtoUniversePairTaskTrackD0 { Configurable confPDGCodeD0bar{"confPDGCodeD0bar", -421, "D0bar meson - PDG code"}; Configurable confMinPtD0D0bar{"confMinPtD0D0bar", 1.0, "D0/D0bar sel. - min. pT"}; Configurable confMaxPtD0D0bar{"confMaxPtD0D0bar", 3.0, "D0/D0bar sel. - max. pT"}; - Configurable confMinInvMassD0D0bar{"confMinInvMassD0D0bar", 1.65, "D0/D0bar sel. - min. invMass"}; - Configurable confMaxInvMassD0D0bar{"confMaxInvMassD0D0bar", 2.05, "D0/D0bar sel. - max. invMass"}; - Configurable confMaxProbMlClass1Bg{"confMaxProbMlClass1Bg", 0.4, "ML: max prob. that D0/D0bar cand. is from the backgound"}; + Configurable minInvMassD0D0barSignal{"minInvMassD0D0barSignal", 1.81, "Min. inv. mass of D0/D0bar for signal region"}; + Configurable maxInvMassD0D0barSignal{"maxInvMassD0D0barSignal", 1.922, "Max. inv. mass of D0/D0bar for signal region"}; + Configurable minInvMassD0D0barLeftSB{"minInvMassD0D0barLeftSB", 1.65, "Min. inv. mass of D0/D0bar for left SB region"}; + Configurable maxInvMassD0D0barLeftSB{"maxInvMassD0D0barLeftSB", 1.754, "Max. inv. mass of D0/D0bar for left SB region"}; + Configurable minInvMassD0D0barRightSB{"minInvMassD0D0barRightSB", 1.978, "Min. inv. mass of D0/D0bar for right SB region"}; + Configurable maxInvMassD0D0barRightSB{"maxInvMassD0D0barRightSB", 2.09, "Max. inv. mass of D0/D0bar for right SB region"}; } ConfDmesons; struct : o2::framework::ConfigurableGroup { - Configurable confSignalRegionMin{"confSignalRegionMin", 1.810, "Min. inv. mass for D0/D0bar in the signal region"}; - Configurable confSignalRegionMax{"confSignalRegionMax", 1.922, "Max. inv. mass for D0/D0bar in the signal region"}; - Configurable confMinInvMassLeftSB{"confMinInvMassLeftSB", 1.642, "Min. inv. mass for D0/D0bar in the left sideband region"}; - Configurable confMaxInvMassLeftSB{"confMaxInvMassLeftSB", 1.754, "Max. inv. mass for D0/D0bar in the left sideband region"}; - Configurable confMinInvMassRightSB{"confMinInvMassRightSB", 1.978, "Min. inv. mass for D0/D0bar in the right sideband region"}; - Configurable confMaxInvMassRightSB{"confMaxInvMassRightSB", 2.090, "Max. inv. mass for D0/D0bar in the right sideband region"}; - } ConfD0D0barSideBand; + Configurable confMaxProbMlClass1Bg{"confMaxProbMlClass1Bg", 0.4, "ML: max prob. that D0/D0bar cand. is from the backgound"}; + Configurable confMinProbMlClass2Prompt{"confMinProbMlClass2Prompt", 0.05, "ML: min prob. that D0/D0bar cand. is prompt"}; + Configurable confMaxProbMlClass3NonPrompt{"confMaxProbMlClass3NonPrompt", 1.0, "ML: max prob. that D0/D0bar cand. is non-prompt"}; + Configurable confClass1BgProbStep{"confClass1BgProbStep", 0.05, "ML: prob. step for score class 1"}; + Configurable confClass1BgProbStart{"confClass1BgProbStart", 0.05, "ML: starting prob. value in optimization for score class 1"}; + Configurable confClass2PromptProbStep{"confClass2PromptProbStep", 0.05, "ML: prob. step for score class 2 - prompt"}; + Configurable confClass2PromptProbStart{"confClass2PromptProbStart", 0.1, "ML: starting prob. value in optimization for score class 2"}; + Configurable confClass3NonPromptProbStep{"confClass3NonPromptProbStep", 0.05, "ML: prob. step for score class 2 - non-prompt"}; + Configurable confClass3NonPromptProbStart{"confClass3NonPromptProbStart", 0.05, "ML: starting prob. value in optimization for score class 3"}; + } ConfMlOpt; Configurable> binsPt{"binsPt", std::vector{hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits"}; - Configurable confChooseD0trackCorr{"confChooseD0trackCorr", 2, "If 0 - only D0s, 1 - only D0bars, 2 - D0/D0bar (one mass hypo.)"}; + Configurable confChooseD0trackCorr{"confChooseD0trackCorr", 0, "If 0 correlations with D0s, if 1 with D0bars"}; + + // Efficiency + struct : o2::framework::ConfigurableGroup { + Configurable confEfficiencyTrackPath{"confEfficiencyTrackPath", "", "Local path to hadron efficiency TH2F file"}; + Configurable confEfficiencyD0Path{"confEfficiencyD0Path", "", "Local path to D0 efficiency TH2F file"}; + Configurable confEfficiencyTrackTimestamp{"confEfficiencyTrackTimestamp", 0, "(int64_t) Timestamp for hadron"}; + Configurable confEfficiencyD0Timestamp{"confEfficiencyD0Timestamp", 0, "(int64_t) Timestamp for D0"}; + Configurable doEfficiencyCorr{"doEfficiencyCorr", false, "Apply efficiency corrections"}; + } ConfEff; /// Partitions for particle 1 Partition partsTrack = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == int8_t(ConfTrack.confTrackSign)) && (aod::femtouniverseparticle::pt > ConfTrack.confTrackLowPtCut) && (aod::femtouniverseparticle::pt < ConfTrack.confTrackHighPtCut); - Partition> partsTrackMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)); + Partition partsTrackMCReco = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == int8_t(ConfTrack.confTrackSign)) && (aod::femtouniverseparticle::pt > ConfTrack.confTrackLowPtCut) && (aod::femtouniverseparticle::pt < ConfTrack.confTrackHighPtCut); + Partition partsTrackMCTruth = (aod::femtouniverseparticle::partType == static_cast(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (aod::femtouniverseparticle::pidCut == static_cast(ConfTrack.confPDGCodeTrack)) && (aod::femtouniverseparticle::pt > ConfTrack.confTrackLowPtCut) && (aod::femtouniverseparticle::pt < ConfTrack.confTrackHighPtCut); /// Partitions for particle 2 /// Partition with all D0/D0bar mesons (which pass double mass hypothesis) // Partition partsAllDmesons = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda > 0.0f) && (aod::femtouniverseparticle::mAntiLambda > 0.0f); /// Partition with D0/D0bar candidates, which pass only one mass hypothesis - Partition partsOnlyD0D0bar = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda < 0.0f || aod::femtouniverseparticle::mAntiLambda < 0.0f) && (aod::femtouniverseparticle::tempFitVar < ConfDmesons.confMaxProbMlClass1Bg); + Partition partsOnlyD0D0bar = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda < 0.0f || aod::femtouniverseparticle::mAntiLambda < 0.0f) && (aod::femtouniverseparticle::tempFitVar < ConfMlOpt.confMaxProbMlClass1Bg) && (aod::femtouniverseparticle::decayVtxY > ConfMlOpt.confMinProbMlClass2Prompt); /// Partition with D0 mesons only (one mass hypothesis) - Partition partsD0s = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda > ConfDmesons.confMinInvMassD0D0bar) && (aod::femtouniverseparticle::mLambda < ConfDmesons.confMaxInvMassD0D0bar) && (aod::femtouniverseparticle::mAntiLambda < 0.0f) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar) && (aod::femtouniverseparticle::tempFitVar < ConfDmesons.confMaxProbMlClass1Bg); + Partition partsD0s = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda > ConfDmesons.minInvMassD0D0barSignal) && (aod::femtouniverseparticle::mLambda < ConfDmesons.maxInvMassD0D0barSignal) && (aod::femtouniverseparticle::mAntiLambda < 0.0f) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar) && (aod::femtouniverseparticle::tempFitVar < ConfMlOpt.confMaxProbMlClass1Bg) && (aod::femtouniverseparticle::decayVtxY > ConfMlOpt.confMinProbMlClass2Prompt); + /// Partition with D0s selected from the side-band (SB) regions + Partition partsD0sFromSB = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && ((aod::femtouniverseparticle::mLambda > ConfDmesons.minInvMassD0D0barLeftSB && aod::femtouniverseparticle::mLambda < ConfDmesons.maxInvMassD0D0barLeftSB) || (aod::femtouniverseparticle::mLambda > ConfDmesons.minInvMassD0D0barRightSB && aod::femtouniverseparticle::mLambda < ConfDmesons.maxInvMassD0D0barRightSB)) && (aod::femtouniverseparticle::mAntiLambda < 0.0f) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar) && (aod::femtouniverseparticle::tempFitVar < ConfMlOpt.confMaxProbMlClass1Bg) && (aod::femtouniverseparticle::decayVtxY > ConfMlOpt.confMinProbMlClass2Prompt); /// Partition with D0bar mesons only (one mass hypothesis) - Partition partsD0bars = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda < 0.0f) && (aod::femtouniverseparticle::mAntiLambda > ConfDmesons.confMinInvMassD0D0bar) && (aod::femtouniverseparticle::mAntiLambda < ConfDmesons.confMaxInvMassD0D0bar) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar) && (aod::femtouniverseparticle::tempFitVar < ConfDmesons.confMaxProbMlClass1Bg); + Partition partsD0bars = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda < 0.0f) && (aod::femtouniverseparticle::mAntiLambda > ConfDmesons.minInvMassD0D0barSignal) && (aod::femtouniverseparticle::mAntiLambda < ConfDmesons.maxInvMassD0D0barSignal) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar) && (aod::femtouniverseparticle::tempFitVar < ConfMlOpt.confMaxProbMlClass1Bg) && (aod::femtouniverseparticle::decayVtxY > ConfMlOpt.confMinProbMlClass2Prompt); /// Partition for D0/D0bar mesons from MC - Partition> partsD0D0barMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)); - + Partition partsD0D0barMCReco = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda < 0.0f || aod::femtouniverseparticle::mAntiLambda < 0.0f) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar) && (aod::femtouniverseparticle::tempFitVar < ConfMlOpt.confMaxProbMlClass1Bg) && (aod::femtouniverseparticle::decayVtxY > ConfMlOpt.confMinProbMlClass2Prompt); + Partition partsD0D0barMCTruth = (aod::femtouniverseparticle::partType == static_cast(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (aod::femtouniverseparticle::pidCut == static_cast(ConfDmesons.confPDGCodeD0) || aod::femtouniverseparticle::pidCut == static_cast(ConfDmesons.confPDGCodeD0bar)) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar); /// Partition for D0/D0bar daughters Partition partsDmesonsChildren = aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0Child); @@ -186,7 +203,6 @@ struct FemtoUniversePairTaskTrackD0 { ConfigurableAxis confmTBins{"confmTBins", {225, 0., 7.5}, "binning mT"}; ConfigurableAxis confPtBins{"confPtBins", {360, 0., 36.}, "binning pT"}; ConfigurableAxis confInvMassBins{"confInvMassBins", {500, 0., 5.0}, "binning inv. mass"}; - ConfigurableAxis confInvMassFinerBins{"confInvMassFinerBins", {120, 1.5848, 2.1848}, "finer binning of inv. mass"}; Configurable confIsCPR{"confIsCPR", true, "Close Pair Rejection"}; Configurable confCPRPlotPerRadii{"confCPRPlotPerRadii", false, "Plot CPR per radii"}; @@ -197,19 +213,34 @@ struct FemtoUniversePairTaskTrackD0 { Configurable confCPRChosenRadii{"confCPRChosenRadii", 0.80, "Delta Eta cut for Close Pair Rejection"}; Configurable applyMLOpt{"applyMLOpt", false, "Enable for ML selection optimization"}; + Configurable confRemoveSoftPions{"confRemoveSoftPions", false, "Enable to remove soft pions from D* decays"}; + Configurable confSoftPionD0Flag{"confSoftPionD0Flag", false, "Enable soft pion check for D0s"}; + Configurable confSoftPionD0barFlag{"confSoftPionD0barFlag", false, "Enable soft pion check for D0bars"}; + Configurable sigmaSoftPiInvMass{"sigmaSoftPiInvMass", 0.1, "Sigma value from the inv. mass fit for soft pions"}; + // Event mixing configurables + Configurable confNEventsMix{"confNEventsMix", 5, "Number of events for mixing"}; - FemtoUniverseFemtoContainer sameEventFemtoCont; - FemtoUniverseFemtoContainer mixedEventFemtoCont; FemtoUniverseAngularContainer sameEventAngularCont; FemtoUniverseAngularContainer mixedEventAngularCont; FemtoUniversePairCleaner pairCleaner; FemtoUniverseDetaDphiStar pairCloseRejection; + FemtoUniverseSoftPionRemoval softPionRemoval; FemtoUniverseTrackSelection trackCuts; + // Axes for BDT score classes' histograms + AxisSpec axisBdtScore{100, 0.f, 1.f}; + AxisSpec axisSelStatus{2, -0.5f, 1.5f}; /// Histogram output HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry mixQaRegistry{"mixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry mcRecoRegistry{"mcRecoRegistry", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry mcTruthRegistry{"mcTruthRegistry", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + + // Efficiency + EfficiencyConfigurableGroup effConfGroup; + EfficiencyCalculator efficiencyCalculator{&effConfGroup}; + float weight = 1.0; HistogramRegistry registry{"registry", {{"hInvMassD0", ";#it{M}(K^{-}#pi^{+}) (GeV/#it{c}^{2});counts", {HistType::kTH1F, {confInvMassBins}}}, @@ -228,21 +259,19 @@ struct FemtoUniversePairTaskTrackD0 { {"hDecayLengthD0bar", ";decay length (cm);counts", {HistType::kTH1F, {{800, 0., 4.}}}}, {"hPtDaughters", ";#it{p}_{T} (GeV/#it{c});counts", {HistType::kTH1F, {{300, 0., 12.}}}}, {"hSignDaughters", ";sign ;counts", {HistType::kTH1F, {{10, -2.5, 2.5}}}}, - {"hbetaDaughters", "; p (GeV/#it{c}); TOF #beta", {HistType::kTH2F, {{300, 0., 15.}, {200, 0., 2.}}}}, - {"hdEdxDaughters", "; p (GeV/#it{c}); TPC dE/dx (KeV/cm)", {HistType::kTH2F, {{300, 0., 15.}, {500, 0., 500.}}}}, {"hDCAxyDaughters", "; #it{DCA}_{xy} (cm); counts", {HistType::kTH1F, {{140, 0., 0.14}}}}, {"hDCAzDaughters", "; #it{DCA}_{z} (cm); counts", {HistType::kTH1F, {{140, 0., 0.14}}}}}}; // PID for protons bool isProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx { - if (mom < 0.5) { + if (mom < ConfTrack.protonMinPtPidTpcTof) { if (std::abs(nsigmaTPCPr) < ConfBothTracks.confNsigmaTPCProton) { return true; } else { return false; } - } else if (mom > 0.4) { + } else if (mom > ConfTrack.protonMinPtPidTpcTof) { if (std::hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfBothTracks.confNsigmaCombinedProton) { return true; } else { @@ -293,20 +322,17 @@ struct FemtoUniversePairTaskTrackD0 { bool isPionNSigma(float mom, float nsigmaTPCPi, float nsigmaTOFPi) { - //|nsigma_TPC| < 3 for p < 0.5 GeV/c - //|nsigma_combined| < 3 for p > 0.5 - // using configurables: - // confNsigmaTPCPion -> TPC Kaon Sigma for momentum < 0.5 - // confNsigmaCombinedPion -> TPC and TOF Pion Sigma (combined) for momentum > 0.5 + // confNsigmaTPCPion -> TPC Pion Sigma for momentum < 0.5 GeV/c + // confNsigmaCombinedPion -> TPC and TOF Pion Sigma (combined) for momentum > 0.5 GeV/c if (true) { - if (mom < 0.5) { + if (mom < ConfTrack.pionMinPtPidTpcTof) { if (std::abs(nsigmaTPCPi) < ConfBothTracks.confNsigmaTPCPion) { return true; } else { return false; } - } else if (mom > 0.5) { + } else if (mom > ConfTrack.pionMinPtPidTpcTof) { if (std::hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfBothTracks.confNsigmaCombinedPion) { return true; } else { @@ -339,11 +365,21 @@ struct FemtoUniversePairTaskTrackD0 { void init(InitContext&) { + if (effConfGroup.confEfficiencyDoMCTruth) { + // WORK IN PROGRESS + // hMCTruth1.init(&qaRegistry, confBinsTempFitVarpT, confBinsTempFitVarPDG, false, ConfTrack.confTrackPDGCode, false); + // hMCTruth2.init(&qaRegistry, confBinsTempFitVarpT, confBinsTempFitVarPDG, false, 333, false); + } + efficiencyCalculator.init(); + eventHisto.init(&qaRegistry); qaRegistry.add("QA_D0D0barSelection/hInvMassD0", ";#it{M}(K^{-}#pi^{+}) (GeV/#it{c}^{2});counts", kTH1F, {confInvMassBins}); qaRegistry.add("QA_D0D0barSelection/hPtD0", "D^{0} cand.;#it{p}_{T} (GeV/#it{c});counts", kTH1F, {confPtBins}); qaRegistry.add("QA_D0D0barSelection/hInvMassD0bar", ";#it{M}(K^{-}#pi^{+}) (GeV/#it{c}^{2});counts", kTH1F, {confInvMassBins}); qaRegistry.add("QA_D0D0barSelection/hPtD0bar", "#bar{D^{0}} cand.;#it{p}_{T} (GeV/#it{c});counts", kTH1F, {confPtBins}); + qaRegistry.add("QA_D0D0barSelection_SB/hInvMassD0", ";#it{M}(K^{-}#pi^{+}) (GeV/#it{c}^{2});counts", kTH1F, {confInvMassBins}); + qaRegistry.add("QA_D0D0barSelection_SB/hPtD0", "D^{0} cand.;#it{p}_{T} (GeV/#it{c});counts", kTH1F, {confPtBins}); + qaRegistry.add("D0_pos_daugh/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); qaRegistry.add("D0_pos_daugh/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); qaRegistry.add("D0_pos_daugh/pt", "; #it{p_T} (GeV/#it{c}); Counts", kTH1F, {{100, 0, 10}}); @@ -379,6 +415,17 @@ struct FemtoUniversePairTaskTrackD0 { qaRegistry.add("Hadron/nSigmaTPCKa", "; #it{p} (GeV/#it{c}); n#sigma_{TPCKa}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); qaRegistry.add("Hadron/nSigmaTOFKa", "; #it{p} (GeV/#it{c}); n#sigma_{TOFKa}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + // MC truth + mcTruthRegistry.add("MCTruthD0D0bar", "MC Truth D0/D0bar;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{360, 0, 36}, {400, -1.0, 1.0}}}); + mcTruthRegistry.add("MCTruthAllPositivePt", "MC Truth all positive;#it{p}_{T} (GeV/c); counts", {HistType::kTH1F, {{360, 0, 36}}}); + mcTruthRegistry.add("MCTruthAllNegativePt", "MC Truth all negative;#it{p}_{T} (GeV/c); counts", {HistType::kTH1F, {{360, 0, 36}}}); + mcTruthRegistry.add("MCTruthKp", "MC Truth K+;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + mcTruthRegistry.add("MCTruthKm", "MC Truth K-;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + mcTruthRegistry.add("MCTruthPip", "MC Truth #pi+;#it{p}_{T} (GeV/c)", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + mcTruthRegistry.add("MCTruthPim", "MC Truth #pi-;#it{p}_{T} (GeV/c)", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + mcTruthRegistry.add("MCTruthProton", "MC Truth proton;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + mcTruthRegistry.add("MCTruthAntiproton", "MC Truth antiproton;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + trackHistoPartD0D0bar.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarInvMassBins, ConfBothTracks.confIsMC, ConfDmesons.confPDGCodeD0); if (!ConfTrack.confIsSame) { trackHistoPartTrack.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarBins, ConfBothTracks.confIsMC, ConfTrack.confPDGCodeTrack); @@ -387,16 +434,13 @@ struct FemtoUniversePairTaskTrackD0 { mixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); mixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); - sameEventFemtoCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, ConfBothTracks.confIsMC, ConfBothTracks.confUse3D); - mixedEventFemtoCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, ConfBothTracks.confIsMC, ConfBothTracks.confUse3D); sameEventAngularCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, ConfBothTracks.confEtaBins, ConfBothTracks.confPhiBins, ConfBothTracks.confIsMC, ConfBothTracks.confUse3D); mixedEventAngularCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, ConfBothTracks.confEtaBins, ConfBothTracks.confPhiBins, ConfBothTracks.confIsMC, ConfBothTracks.confUse3D); - sameEventFemtoCont.setPDGCodes(ConfDmesons.confPDGCodeD0, ConfTrack.confPDGCodeTrack); - mixedEventFemtoCont.setPDGCodes(ConfDmesons.confPDGCodeD0, ConfTrack.confPDGCodeTrack); sameEventAngularCont.setPDGCodes(ConfDmesons.confPDGCodeD0, ConfTrack.confPDGCodeTrack); mixedEventAngularCont.setPDGCodes(ConfDmesons.confPDGCodeD0, ConfTrack.confPDGCodeTrack); + softPionRemoval.init(&qaRegistry); pairCleaner.init(&qaRegistry); if (confIsCPR.value) { pairCloseRejection.init(&resultRegistry, &qaRegistry, confCPRdeltaPhiCutMin.value, confCPRdeltaPhiCutMax.value, confCPRdeltaEtaCutMin.value, confCPRdeltaEtaCutMax.value, confCPRChosenRadii.value, confCPRPlotPerRadii.value); @@ -408,30 +452,26 @@ struct FemtoUniversePairTaskTrackD0 { // D0/D0bar histograms auto vbins = (std::vector)binsPt; registry.add("D0D0bar_oneMassHypo/hMassVsPt", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("D0D0bar_oneMassHypo/hMassVsPtFinerBinning", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassFinerBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hDeltaPhiSigSig", "SxS correlation;#Delta#varphi (rad);counts", {HistType::kTH1F, {{10, 0.0, o2::constants::math::PI}}}); - registry.add("hDeltaPhiD0BgD0barSig", "B(D0)x S(D0bar) correlation;#Delta#varphi (rad);counts", {HistType::kTH1F, {{10, 0.0, o2::constants::math::PI}}}); - registry.add("hDeltaPhiD0SigD0barBg", "S(D0)x B(D0bar) correlation;#Delta#varphi (rad);counts", {HistType::kTH1F, {{10, 0.0, o2::constants::math::PI}}}); - registry.add("hDeltaPhiBgBg", "BxB correlation;#Delta#varphi (rad);counts", {HistType::kTH1F, {{10, 0.0, o2::constants::math::PI}}}); - registry.add("hPtCand1VsPtCand2", "2-prong candidates;#it{p}_{T} (GeV/#it{c});#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {{vbins, "#it{p}_{T} (GeV/#it{c})"}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hDeltaEtaDeltaPhi", "2-prong candidates;#Delta #eta;#Delta #varphi (rad)", {HistType::kTH2F, {{29, -2., 2.}, {29, 0.0, o2::constants::math::PI}}}); + registry.add("D0D0bar_oneMassHypo/hMassVsPtReflected", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("D0D0bar_oneMassHypo/hMassVsPtD0", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("D0D0bar_oneMassHypo/hMassVsPtD0bar", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("D0D0bar_oneMassHypo/hMassVsPtD0Reflected", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("D0D0bar_oneMassHypo/hMassVsPtD0barReflected", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + // Histograms for BDT score classes' check + registry.add("DebugBdt/hBdtScore1VsStatus", ";BDT score;status", {HistType::kTH2F, {axisBdtScore, axisSelStatus}}); + registry.add("DebugBdt/hBdtScore2VsStatus", ";BDT score;status", {HistType::kTH2F, {axisBdtScore, axisSelStatus}}); + registry.add("DebugBdt/hBdtScore3VsStatus", ";BDT score;status", {HistType::kTH2F, {axisBdtScore, axisSelStatus}}); if (applyMLOpt) { - registry.add("D0D0bar_MLSel/hMassVsPt001", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("D0D0bar_MLSel/hMassVsPt0015", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("D0D0bar_MLSel/hMassVsPt002", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("D0D0bar_MLSel/hMassVsPt0025", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("D0D0bar_MLSel/hMassVsPt003", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("D0D0bar_MLSel/hMassVsPt004", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("D0D0bar_MLSel/hMassVsPt005", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("D0D0bar_MLSel/hMassVsPt006", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("D0D0bar_MLSel/hMassVsPt007", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("D0D0bar_MLSel/hMassVsPt008", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("D0D0bar_MLSel/hMassVsPt009", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("D0D0bar_MLSel/hMassVsPt01", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("D0D0bar_MLSel/hMassVsPt015", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("D0D0bar_MLSel/hMassVsPt02", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("D0D0bar_MLSel/hMassVsPt025", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("D0D0bar_MLSel/hMassVsPt03", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("D0D0bar_MLSel/hMassVsPt1", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("D0D0bar_MLSel/hMassVsPt2", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("D0D0bar_MLSel/hMassVsPt3", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("D0D0bar_MLSel/hMassVsPt4", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("D0D0bar_MLSel/hMassVsPt5", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("D0D0bar_MLSel/hMassVsPt6", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("D0D0bar_MLSel/hMassVsPt7", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("D0D0bar_MLSel/hMassVsPt8", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("D0D0bar_MLSel/hMassVsPt9", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("D0D0bar_MLSel/hMassVsPt10", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); } } @@ -442,7 +482,7 @@ struct FemtoUniversePairTaskTrackD0 { eventHisto.fillQA(col); } - void processD0MLOpt(o2::aod::FdCollision const& col, FemtoFullParticles const&) + void processD0MLOptBg(o2::aod::FdCollision const& col, FemtoFullParticles const&) { auto groupD0D0barCands = partsOnlyD0D0bar->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); @@ -450,82 +490,117 @@ struct FemtoUniversePairTaskTrackD0 { for (auto const& charmCand : groupD0D0barCands) { // D0 candidates if (charmCand.mLambda() > 0.0f && charmCand.mAntiLambda() < 0.0f) { - if (charmCand.tempFitVar() < 0.01) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt001"), charmCand.mLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.015) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt0015"), charmCand.mLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.02) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt002"), charmCand.mLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.025) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt0025"), charmCand.mLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.03) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt003"), charmCand.mLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.04) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt004"), charmCand.mLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.05) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt005"), charmCand.mLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.06) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt006"), charmCand.mLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.07) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt007"), charmCand.mLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.08) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt008"), charmCand.mLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.09) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt009"), charmCand.mLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.1) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt01"), charmCand.mLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.15) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt015"), charmCand.mLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.2) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt02"), charmCand.mLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.25) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt025"), charmCand.mLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.3) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt03"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt1"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt2"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 2.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt3"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 3.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt4"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 4.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt5"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 5.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt6"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 6.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt7"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 7.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt8"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 8.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt9"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 9.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt10"), charmCand.mLambda(), charmCand.pt()); } // DObar candidates if (charmCand.mLambda() < 0.0f && charmCand.mAntiLambda() > 0.0f) { - if (charmCand.tempFitVar() < 0.01) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt001"), charmCand.mAntiLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.015) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt0015"), charmCand.mAntiLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.02) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt002"), charmCand.mAntiLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.025) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt0025"), charmCand.mAntiLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.03) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt003"), charmCand.mAntiLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.04) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt004"), charmCand.mAntiLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.05) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt005"), charmCand.mAntiLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.06) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt006"), charmCand.mAntiLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.07) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt007"), charmCand.mAntiLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.08) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt008"), charmCand.mAntiLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.09) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt009"), charmCand.mAntiLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.1) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt01"), charmCand.mAntiLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.15) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt015"), charmCand.mAntiLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.2) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt02"), charmCand.mAntiLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.25) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt025"), charmCand.mAntiLambda(), charmCand.pt()); - if (charmCand.tempFitVar() < 0.3) - registry.fill(HIST("D0D0bar_MLSel/hMassVsPt03"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt1"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt2"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 2.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt3"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 3.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt4"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 4.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt5"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 5.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt6"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 6.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt7"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 7.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt8"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 8.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt9"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 9.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt10"), charmCand.mAntiLambda(), charmCand.pt()); + } + } + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackD0, processD0MLOptBg, "Enable filling QA plots for ML Bg D0/D0bar selection optimization", false); + + void processD0MLOptBgAndPrompt(o2::aod::FdCollision const& col, FemtoFullParticles const&) + { + auto groupD0D0barCands = partsOnlyD0D0bar->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + // loop over selected D0/D0bar candidates + for (auto const& charmCand : groupD0D0barCands) { + // D0 candidates + if (charmCand.decayVtxY() > ConfMlOpt.confClass2PromptProbStart) { + if (charmCand.mLambda() > 0.0f && charmCand.mAntiLambda() < 0.0f) { + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt1"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt2"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 2.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt3"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 3.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt4"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 4.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt5"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 5.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt6"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 6.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt7"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 7.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt8"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 8.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt9"), charmCand.mLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 9.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt10"), charmCand.mLambda(), charmCand.pt()); + } + // DObar candidates + if (charmCand.mLambda() < 0.0f && charmCand.mAntiLambda() > 0.0f) { + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt1"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt2"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 2.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt3"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 3.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt4"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 4.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt5"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 5.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt6"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 6.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt7"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 7.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt8"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 8.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt9"), charmCand.mAntiLambda(), charmCand.pt()); + if (charmCand.tempFitVar() < ConfMlOpt.confClass1BgProbStart + 9.0 * ConfMlOpt.confClass1BgProbStep) + registry.fill(HIST("D0D0bar_MLSel/hMassVsPt10"), charmCand.mAntiLambda(), charmCand.pt()); + } } } } - PROCESS_SWITCH(FemtoUniversePairTaskTrackD0, processD0MLOpt, "Enable filling QA plots for ML D0/D0bar selection optimization", false); + PROCESS_SWITCH(FemtoUniversePairTaskTrackD0, processD0MLOptBgAndPrompt, "Enable filling QA plots for ML Bg and Prompt D0/D0bar selection optimization", false); void processQAD0D0barSel(o2::aod::FdCollision const& col, FemtoFullParticles const&) { auto groupPartsD0s = partsD0s->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto groupPartsD0bars = partsD0bars->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto groupPartsD0sFromSB = partsD0sFromSB->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); // loop over selected D0 candidates for (auto const& d0cand : groupPartsD0s) { @@ -539,6 +614,13 @@ struct FemtoUniversePairTaskTrackD0 { qaRegistry.fill(HIST("QA_D0D0barSelection/hInvMassD0bar"), d0barcand.mAntiLambda()); qaRegistry.fill(HIST("QA_D0D0barSelection/hPtD0bar"), d0barcand.pt()); } + + // loop over selected D0 candidates from SB regions + for (auto const& d0SB : groupPartsD0sFromSB) { + + qaRegistry.fill(HIST("QA_D0D0barSelection_SB/hInvMassD0"), d0SB.mLambda()); + qaRegistry.fill(HIST("QA_D0D0barSelection_SB/hPtD0"), d0SB.pt()); + } } PROCESS_SWITCH(FemtoUniversePairTaskTrackD0, processQAD0D0barSel, "Enable filling QA plots for selected D0/D0bar cand.", true); @@ -551,9 +633,16 @@ struct FemtoUniversePairTaskTrackD0 { for (auto const& d0d0bar : groupPartsOnlyD0D0bar) { registry.fill(HIST("hPtD0D0bar"), d0d0bar.pt()); + // BDT score classes + registry.fill(HIST("DebugBdt/hBdtScore1VsStatus"), d0d0bar.decayVtxX(), 1); + registry.fill(HIST("DebugBdt/hBdtScore2VsStatus"), d0d0bar.decayVtxY(), 1); + registry.fill(HIST("DebugBdt/hBdtScore3VsStatus"), d0d0bar.decayVtxZ(), 1); if (d0d0bar.mLambda() > 0.0f && d0d0bar.mAntiLambda() < 0.0f) { registry.fill(HIST("D0D0bar_oneMassHypo/hMassVsPt"), d0d0bar.mLambda(), d0d0bar.pt()); + registry.fill(HIST("D0D0bar_oneMassHypo/hMassVsPtD0"), d0d0bar.mLambda(), d0d0bar.pt()); + registry.fill(HIST("D0D0bar_oneMassHypo/hMassVsPtReflected"), std::abs(d0d0bar.mAntiLambda()), d0d0bar.pt()); + registry.fill(HIST("D0D0bar_oneMassHypo/hMassVsPtD0Reflected"), std::abs(d0d0bar.mAntiLambda()), d0d0bar.pt()); registry.fill(HIST("hInvMassD0"), d0d0bar.mLambda()); registry.fill(HIST("hPtD0"), d0d0bar.pt()); registry.fill(HIST("hPhiD0"), d0d0bar.phi()); @@ -561,6 +650,9 @@ struct FemtoUniversePairTaskTrackD0 { } if (d0d0bar.mLambda() < 0.0f && d0d0bar.mAntiLambda() > 0.0f) { registry.fill(HIST("D0D0bar_oneMassHypo/hMassVsPt"), d0d0bar.mAntiLambda(), d0d0bar.pt()); + registry.fill(HIST("D0D0bar_oneMassHypo/hMassVsPtD0bar"), d0d0bar.mAntiLambda(), d0d0bar.pt()); + registry.fill(HIST("D0D0bar_oneMassHypo/hMassVsPtReflected"), std::abs(d0d0bar.mLambda()), d0d0bar.pt()); + registry.fill(HIST("D0D0bar_oneMassHypo/hMassVsPtD0barReflected"), std::abs(d0d0bar.mLambda()), d0d0bar.pt()); registry.fill(HIST("hInvMassD0bar"), d0d0bar.mAntiLambda()); registry.fill(HIST("hPtD0bar"), d0d0bar.pt()); registry.fill(HIST("hPhiD0bar"), d0d0bar.phi()); @@ -600,63 +692,6 @@ struct FemtoUniversePairTaskTrackD0 { } PROCESS_SWITCH(FemtoUniversePairTaskTrackD0, processD0mesons, "Enable processing D0 mesons", true); - // D0-D0bar pair correlations (side-band methode) - void processSideBand(o2::aod::FdCollision const& col, FemtoFullParticles const&) - { - auto groupPartsOnlyD0D0bar = partsOnlyD0D0bar->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - - double deltaPhi = 0.0; - double deltaEta = 0.0; - - // loop over D0/D0bar candidates (ONLY) - for (auto const& cand1 : groupPartsOnlyD0D0bar) { - // Check if the first candidate is D0 meson - if (cand1.mLambda() < 0.0f && cand1.mAntiLambda() > 0.0f) { - continue; - } - - for (auto const& cand2 : groupPartsOnlyD0D0bar) { - // Check if the second candidate is D0bar meson - if (cand2.mLambda() > 0.0f && cand2.mAntiLambda() < 0.0f) { - continue; - } - // deltaPhi = getDeltaPhi(cand1.phi(), cand2.phi()); - deltaPhi = wrapDeltaPhi0PI(cand1.phi(), cand2.phi()); - deltaEta = cand2.eta() - cand1.eta(); - - // General histograms - registry.fill(HIST("hPtCand1VsPtCand2"), cand1.pt(), cand2.pt()); - registry.fill(HIST("hDeltaEtaDeltaPhi"), deltaEta, deltaPhi); - - // ----------------------------------- Creating D0-D0bar pairs correlations ------------------------------------------------ - if (cand1.mLambda() > ConfD0D0barSideBand.confSignalRegionMin.value && cand1.mLambda() < ConfD0D0barSideBand.confSignalRegionMax.value) { - // S(D0) x S(D0bar) correlation - if (cand2.mAntiLambda() > ConfD0D0barSideBand.confSignalRegionMin.value && cand2.mAntiLambda() < ConfD0D0barSideBand.confSignalRegionMax.value) { - registry.fill(HIST("hDeltaPhiSigSig"), deltaPhi); - } - // S(D0) x B(D0bar) correlation - if ((cand2.mAntiLambda() > ConfD0D0barSideBand.confMinInvMassLeftSB.value && cand2.mAntiLambda() < ConfD0D0barSideBand.confMaxInvMassLeftSB.value) || - (cand2.mAntiLambda() > ConfD0D0barSideBand.confMinInvMassRightSB.value && cand2.mAntiLambda() < ConfD0D0barSideBand.confMaxInvMassRightSB.value)) { - registry.fill(HIST("hDeltaPhiD0SigD0barBg"), deltaPhi); - } - } - if ((cand1.mLambda() > ConfD0D0barSideBand.confMinInvMassLeftSB.value && cand1.mLambda() < ConfD0D0barSideBand.confMaxInvMassLeftSB.value) || - (cand1.mLambda() > ConfD0D0barSideBand.confMinInvMassRightSB.value && cand1.mLambda() < ConfD0D0barSideBand.confMaxInvMassRightSB.value)) { - // B(D0) x S (D0bar) correlation - if (cand2.mAntiLambda() > ConfD0D0barSideBand.confSignalRegionMin.value && cand2.mAntiLambda() < ConfD0D0barSideBand.confSignalRegionMax.value) { - registry.fill(HIST("hDeltaPhiD0BgD0barSig"), deltaPhi); - } - // B(D0) x B(D0bar) correlation - if ((cand2.mAntiLambda() > ConfD0D0barSideBand.confMinInvMassLeftSB.value && cand2.mAntiLambda() < ConfD0D0barSideBand.confMaxInvMassLeftSB.value) || - (cand2.mAntiLambda() > ConfD0D0barSideBand.confMinInvMassRightSB.value && cand2.mAntiLambda() < ConfD0D0barSideBand.confMaxInvMassRightSB.value)) { - registry.fill(HIST("hDeltaPhiBgBg"), deltaPhi); - } - } - } // It is the end of the for loop over D0bar mesons - } // It is the end of the for loop over all candidates - } - PROCESS_SWITCH(FemtoUniversePairTaskTrackD0, processSideBand, "Enable processing side-band methode", false); - /// This function processes the same event and takes care of all the histogramming /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... /// @tparam PartitionType @@ -709,18 +744,27 @@ struct FemtoUniversePairTaskTrackD0 { continue; } } + // Soft Pion Removal + if (confRemoveSoftPions) { + if (softPionRemoval.isSoftPion(track, d0candidate, parts, confSoftPionD0Flag, confSoftPionD0barFlag, sigmaSoftPiInvMass)) { + continue; + } + } // // Close Pair Rejection if (confIsCPR.value) { if (pairCloseRejection.isClosePair(track, d0candidate, parts, magFieldTesla, femto_universe_container::EventType::same)) { continue; } } - // Track Cleaning if (!pairCleaner.isCleanPair(track, d0candidate, parts)) { continue; } - sameEventFemtoCont.setPair(track, d0candidate, multCol, ConfBothTracks.confUse3D); + // Efficiency + weight = 1.0f; + if (ConfEff.doEfficiencyCorr) { + weight = efficiencyCalculator.getWeight(ParticleNo::ONE, track) * efficiencyCalculator.getWeight(ParticleNo::TWO, d0candidate); + } sameEventAngularCont.setPair(track, d0candidate, multCol, ConfBothTracks.confUse3D); } } @@ -734,7 +778,6 @@ struct FemtoUniversePairTaskTrackD0 { fillCollision(col); auto thegroupPartsTrack = partsTrack->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - auto thegroupPartsOnlyD0D0bar = partsOnlyD0D0bar->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto theGroupPartsD0s = partsD0s->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto theGroupPartsD0bars = partsD0bars->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); @@ -745,15 +788,23 @@ struct FemtoUniversePairTaskTrackD0 { case 1: doSameEvent(thegroupPartsTrack, theGroupPartsD0bars, parts, col.magField(), col.multNtr()); break; - case 2: - doSameEvent(thegroupPartsTrack, thegroupPartsOnlyD0D0bar, parts, col.magField(), col.multNtr()); - break; default: break; } } PROCESS_SWITCH(FemtoUniversePairTaskTrackD0, processSameEvent, "Enable processing same event", true); + void processSameEventSB(o2::aod::FdCollision const& col, FemtoFullParticles const& parts) + { + fillCollision(col); + + auto groupPartsTrack = partsTrack->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto groupPartsD0sFromSB = partsD0sFromSB->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + doSameEvent(groupPartsTrack, groupPartsD0sFromSB, parts, col.magField(), col.multNtr()); + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackD0, processSameEventSB, "Enable processing same event", true); + /// process function for to call doSameEvent with Monte Carlo /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) /// \param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth @@ -764,8 +815,8 @@ struct FemtoUniversePairTaskTrackD0 { { fillCollision(col); - auto thegroupPartsD0 = partsD0D0barMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - auto thegroupPartsTrack = partsTrackMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsD0 = partsD0D0barMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTrack = partsTrackMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); doSameEvent(thegroupPartsTrack, thegroupPartsD0, parts, col.magField(), col.multNtr()); } @@ -791,14 +842,28 @@ struct FemtoUniversePairTaskTrackD0 { continue; } } + // // Soft Pion Removal + if (confRemoveSoftPions) { + if (softPionRemoval.isSoftPion(track, d0candidate, parts, confSoftPionD0Flag, confSoftPionD0barFlag, sigmaSoftPiInvMass)) { + continue; + } + } // // Close Pair Rejection if (confIsCPR.value) { if (pairCloseRejection.isClosePair(track, d0candidate, parts, magFieldTesla, femto_universe_container::EventType::mixed)) { continue; } } + // // Track Cleaning + if (!pairCleaner.isCleanPair(track, d0candidate, parts)) { + continue; + } + // Efficiency + weight = 1.0f; + if (ConfEff.doEfficiencyCorr) { + weight = efficiencyCalculator.getWeight(ParticleNo::ONE, track) * efficiencyCalculator.getWeight(ParticleNo::TWO, d0candidate); + } - mixedEventFemtoCont.setPair(track, d0candidate, multCol, ConfBothTracks.confUse3D); mixedEventAngularCont.setPair(track, d0candidate, multCol, ConfBothTracks.confUse3D); } } @@ -809,13 +874,12 @@ struct FemtoUniversePairTaskTrackD0 { void processMixedEvent(o2::aod::FdCollisions const& cols, FemtoFullParticles const& parts) { - for (auto const& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + for (auto const& [collision1, collision2] : soa::selfCombinations(colBinning, confNEventsMix, -1, cols, cols)) { const int multiplicityCol = collision1.multNtr(); mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); auto groupPartsTrack = partsTrack->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - auto groupPartsOnlyD0D0bar = partsOnlyD0D0bar->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto theGroupPartsD0s = partsD0s->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto theGroupPartsD0bars = partsD0bars->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); @@ -835,9 +899,6 @@ struct FemtoUniversePairTaskTrackD0 { case 1: doMixedEvent(groupPartsTrack, theGroupPartsD0bars, parts, magFieldTesla1, multiplicityCol); break; - case 2: - doMixedEvent(groupPartsTrack, groupPartsOnlyD0D0bar, parts, magFieldTesla1, multiplicityCol); - break; default: break; } @@ -845,6 +906,33 @@ struct FemtoUniversePairTaskTrackD0 { } PROCESS_SWITCH(FemtoUniversePairTaskTrackD0, processMixedEvent, "Enable processing mixed events", true); + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoUniverseParticleTable + void processMixedEventSB(o2::aod::FdCollisions const& cols, FemtoFullParticles const& parts) + { + for (auto const& [collision1, collision2] : soa::selfCombinations(colBinning, confNEventsMix, -1, cols, cols)) { + + const int multiplicityCol = collision1.multNtr(); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + + auto groupPartsTrack = partsTrack->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + auto groupPartsD0sFromSB = partsD0sFromSB->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + /// \todo before mixing we should check whether both collisions contain a pair of particles! + // if (partsD0.size() == 0 || kNPart2Evt1 == 0 || kNPart1Evt2 == 0 || partsTrack.size() == 0 ) continue; + + doMixedEvent(groupPartsTrack, groupPartsD0sFromSB, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackD0, processMixedEventSB, "Enable processing mixed events", false); + /// brief process function for to call doMixedEvent with Monte Carlo /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) /// @param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth @@ -853,13 +941,13 @@ struct FemtoUniversePairTaskTrackD0 { soa::Join const& parts, o2::aod::FdMCParticles const&) { - for (auto const& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + for (auto const& [collision1, collision2] : soa::selfCombinations(colBinning, confNEventsMix, -1, cols, cols)) { const int multiplicityCol = collision1.multNtr(); mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); - auto groupPartsTrack = partsTrackMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - auto groupPartsD0 = partsD0D0barMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTrack = partsTrackMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + auto groupPartsD0 = partsD0D0barMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); const auto& magFieldTesla1 = collision1.magField(); const auto& magFieldTesla2 = collision2.magField(); @@ -874,6 +962,54 @@ struct FemtoUniversePairTaskTrackD0 { } } PROCESS_SWITCH(FemtoUniversePairTaskTrackD0, processMixedEventMC, "Enable processing mixed events MC", false); + + void processMCReco(FemtoMCParticles const&, aod::FdMCParticles const&) + { + // WORK IN PROGRESS + // for (auto const& part : parts) {} + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackD0, processMCReco, "Process MC reco data", false); + + void processMCTruth(aod::FDParticles const& parts) // WORK IN PROGRESS + { + for (auto const& part : parts) { + if (part.partType() != uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) + continue; + + int pdgCode = static_cast(part.pidCut()); + const auto& pdgParticle = pdgMC->GetParticle(pdgCode); + if (!pdgParticle) { + continue; + } + + if (pdgParticle->Charge() > 0.0) { + mcTruthRegistry.fill(HIST("MCTruthAllPositivePt"), part.pt()); + } + if (pdgCode == 321) { + // mcTruthRegistry.fill(HIST("MCtruthKp"), part.pt(), part.eta()); + // mcTruthRegistry.fill(HIST("MCtruthKpPt"), part.pt()); + } + if (pdgCode == 333) { + // mcTruthRegistry.fill(HIST("MCtruthPhi"), part.pt(), part.eta()); + // continue; + } + if (pdgCode == 2212) { + // mcTruthRegistry.fill(HIST("MCtruthPpos"), part.pt(), part.eta()); + } + + if (pdgParticle->Charge() < 0.0) { + mcTruthRegistry.fill(HIST("MCTruthAllNegativePt"), part.pt()); + } + if (pdgCode == -321) { + // mcTruthRegistry.fill(HIST("MCtruthKm"), part.pt(), part.eta()); + // mcTruthRegistry.fill(HIST("MCtruthKmPt"), part.pt()); + } + if (pdgCode == -2212) { + // mcTruthRegistry.fill(HIST("MCtruthPneg"), part.pt(), part.eta()); + } + } + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackD0, processMCTruth, "Process MC truth data", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)