From 40344b5a4a79be8cb97331cb9bb3324371893bc0 Mon Sep 17 00:00:00 2001 From: Stefano Cannito Date: Wed, 2 Jul 2025 10:33:43 +0200 Subject: [PATCH 1/4] First commit for ResonanceTreeCreator --- PWGLF/TableProducer/Resonances/CMakeLists.txt | 5 + .../Resonances/resonanceTreeCreator.cxx | 334 ++++++++++++++++++ 2 files changed, 339 insertions(+) create mode 100644 PWGLF/TableProducer/Resonances/resonanceTreeCreator.cxx diff --git a/PWGLF/TableProducer/Resonances/CMakeLists.txt b/PWGLF/TableProducer/Resonances/CMakeLists.txt index 79b69b5b071..ce811fdcc97 100644 --- a/PWGLF/TableProducer/Resonances/CMakeLists.txt +++ b/PWGLF/TableProducer/Resonances/CMakeLists.txt @@ -49,3 +49,8 @@ o2physics_add_dpl_workflow(heptaquarktable SOURCES HeptaQuarktable.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsVertexing COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(resonance-tree-creator + SOURCES resonanceTreeCreator.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/PWGLF/TableProducer/Resonances/resonanceTreeCreator.cxx b/PWGLF/TableProducer/Resonances/resonanceTreeCreator.cxx new file mode 100644 index 00000000000..3275e3e00b4 --- /dev/null +++ b/PWGLF/TableProducer/Resonances/resonanceTreeCreator.cxx @@ -0,0 +1,334 @@ +// Copyright 2019-2020 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 resonanceTreeCreator.cxx +/// \brief Produces a TTree with machine learning variables for resonances in the LF group +/// \author Stefano Cannito (stefano.cannito@cern.ch) + +#include "Common/DataModel/EventSelection.h" + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +// #include "PWGLF/DataModel/LFResonanceMLTables.h" +#include "PWGLF/DataModel/mcCentrality.h" +#include "PWGLF/Utils/inelGt.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "ReconstructionDataFormats/Track.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +namespace o2::aod +{ +namespace resomlcandidates +{ +// Multiplicity class +DECLARE_SOA_COLUMN(MultClass, multClass, float); //! Event multiplicity class +// Daughter 1 +DECLARE_SOA_COLUMN(PtDaughter1, ptdaughter1, float); //! Transverse momentum of daughter1 (GeV/c) +DECLARE_SOA_COLUMN(PDaughter1, pdaughter1, float); //! Momentum of daughter1 (GeV/c) +DECLARE_SOA_COLUMN(PhiDaughter1, phiDaughter1, float); //! Azimuthal angle of daughter1 (rad) +DECLARE_SOA_COLUMN(EtaDaughter1, etaDaughter1, float); //! Pseudorapidity of daughter1 +DECLARE_SOA_COLUMN(YDaughter1, yDaughter1, float); //! Rapidity of daughter1 +DECLARE_SOA_COLUMN(DCAxyDaughter1, dcaDaughter1, float); //! DCA of daughter1 to primary vertex (cm) +DECLARE_SOA_COLUMN(DCAzDaughter1, dcaZDaughter1, float); //! DCA of daughter1 to primary vertex in z (cm) +DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); //! TPC Nsigma separation for daughter1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcKa1, nSigTpcKa1, float); //! TPC Nsigma separation for daughter1 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF Nsigma separation for daughter1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofKa1, nSigTofKa1, float); //! TOF Nsigma separation for daughter1 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofPi1, nSigTpcTofPi1, float); //! TPC and TOF combined Nsigma separation for daughter1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofKa1, nSigTpcTofKa1, float); //! TPC and TOF combined Nsigma separation for daughter1 with kaon mass hypothesis +// Daughter 2 +DECLARE_SOA_COLUMN(PtDaughter2, ptdaughter2, float); //! Transverse momentum of daughter2 (GeV/c) +DECLARE_SOA_COLUMN(PDaughter2, pdaughter2, float); //! Momentum of daughter2 (in GeV/c) +DECLARE_SOA_COLUMN(PhiDaughter2, phiDaughter2, float); //! Azimuthal angle of daughter2 (rad) +DECLARE_SOA_COLUMN(EtaDaughter2, etaDaughter2, float); //! Pseudorapidity of daughter2 +DECLARE_SOA_COLUMN(YDaughter2, yDaughter2, float); //! Rapidity of daughter2 +DECLARE_SOA_COLUMN(DCAxyDaughter2, dcaDaughter2, float); //! DCA of daughter2 to primary vertex (cm) +DECLARE_SOA_COLUMN(DCAzDaughter2, dcaZDaughter2, float); //! DCA of daughter2 to primary vertex in z (cm) +DECLARE_SOA_COLUMN(NSigTpcPi2, nSigTpcPi2, float); //! TPC Nsigma separation for daughter2 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcKa2, nSigTpcKa2, float); //! TPC Nsigma separation for daughter2 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi2, nSigTofPi2, float); //! TOF Nsigma separation for daughter2 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofKa2, nSigTofKa2, float); //! TOF Nsigma separation for daughter2 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofPi2, nSigTpcTofPi2, float); //! TPC and TOF combined Nsigma separation for daughter2 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofKa2, nSigTpcTofKa2, float); //! TPC and TOF combined Nsigma separation for daughter2 with kaon mass hypothesis +// Candidate +DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate +DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate +DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate +DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! Sign of the candidate +DECLARE_SOA_COLUMN(IsPhi, isPhi, bool); //! Flag to indicate if the candidate is a phi meson +} // namespace resomlcandidates + +DECLARE_SOA_TABLE(ResoMLCandidates, "AOD", "RESOMLCANDIDATES", + resomlcandidates::MultClass, + resomlcandidates::PtDaughter1, + resomlcandidates::PDaughter1, + resomlcandidates::PhiDaughter1, + resomlcandidates::EtaDaughter1, + resomlcandidates::YDaughter1, + resomlcandidates::DCAxyDaughter1, + resomlcandidates::DCAzDaughter1, + resomlcandidates::NSigTpcPi1, + resomlcandidates::NSigTpcKa1, + resomlcandidates::NSigTofPi1, + resomlcandidates::NSigTofKa1, + resomlcandidates::NSigTpcTofPi1, + resomlcandidates::NSigTpcTofKa1, + resomlcandidates::PtDaughter2, + resomlcandidates::PDaughter2, + resomlcandidates::PhiDaughter2, + resomlcandidates::EtaDaughter2, + resomlcandidates::YDaughter2, + resomlcandidates::DCAxyDaughter2, + resomlcandidates::DCAzDaughter2, + resomlcandidates::NSigTpcPi2, + resomlcandidates::NSigTpcKa2, + resomlcandidates::NSigTofPi2, + resomlcandidates::NSigTofKa2, + resomlcandidates::NSigTpcTofPi2, + resomlcandidates::NSigTpcTofKa2, + resomlcandidates::M, + resomlcandidates::Pt, + resomlcandidates::P, + resomlcandidates::Phi, + resomlcandidates::Eta, + resomlcandidates::Y, + resomlcandidates::Sign, + resomlcandidates::IsPhi); + +namespace resomlselection +{ +DECLARE_SOA_COLUMN(PhiBDTScore, gammaBDTScore, float); +} // namespace resomlselection + +DECLARE_SOA_TABLE(ResoPhiMLSelection, "AOD", "RESOPHIMLSELECTION", + resomlselection::PhiBDTScore); +} // namespace o2::aod + +struct resonanceTreeCreator { + // Production of the TTree + Produces resoMLCandidates; + + // Configurables for track selection + Configurable cfgCutCharge{"cfgCutCharge", 0.0f, "Cut on the signed transverse momentum to select positive or negative tracks"}; + + // Configurables for production of training samples + Configurable fillOnlySignal{"fillOnlySignal", false, "Flag to fill derived tables with signal for ML trainings"}; + Configurable fillOnlyBackground{"fillOnlyBackground", false, "Flag to fill derived tables with background for ML trainings"}; + Configurable downSampleBkgFactor{"downSampleBkgFactor", 0.5f, "Fraction of background candidates to keep for ML trainings"}; + Configurable ptMaxForDownSample{"ptMaxForDownSample", 10.0f, "Maximum pt for the application of the downsampling factor"}; + + // Defining the type of the collisions for data and MC + using SelCollisions = soa::Join; + using SimCollisions = soa::Join; + + // Defining the type of the tracks for data and MC + using FullTracks = soa::Join; + using FullMCTracks = soa::Join; + + Partition posTracks = aod::track::signed1Pt > cfgCutCharge; + Partition negTracks = aod::track::signed1Pt < cfgCutCharge; + + Partition posMCTracks = aod::track::signed1Pt > cfgCutCharge; + Partition negMCTracks = aod::track::signed1Pt < cfgCutCharge; + + // Cache for the tracks + SliceCache cache; + + // Necessary to flag INEL>0 events in GenMC + Service pdgDB; + + enum ParticleType { + Pi, + Ka, + Pr + }; + + // Constants + double massPi = o2::constants::physics::MassPiPlus; + double massKa = o2::constants::physics::MassKPlus; + + void init(InitContext&) + { + } + + // Combine Nsigma values from TPC and TOF + template + float combineNSigma(const T& track) + { + float nSigmaTPC, nSigmaTOF; + switch (massHypo) { + case Pi: + nSigmaTPC = track.tpcNSigmaPi(); + nSigmaTOF = track.tofNSigmaPi(); + break; + case Ka: + nSigmaTPC = track.tpcNSigmaKa(); + nSigmaTOF = track.tofNSigmaKa(); + break; + case Pr: + nSigmaTPC = track.tpcNSigmaPr(); + nSigmaTOF = track.tofNSigmaPr(); + break; + default: + break; + } + + static constexpr float defaultNSigmaTolerance = .1f; + static constexpr float defaultNSigma = -999.f + defaultNSigmaTolerance; + + if (nSigmaTPC > defaultNSigma && nSigmaTOF > defaultNSigma) + return std::sqrt(0.5f * std::pow(nSigmaTPC, 2) + std::pow(nSigmaTOF, 2)); + if (nSigmaTPC > defaultNSigma) + return std::abs(nSigmaTPC); + if (nSigmaTOF > defaultNSigma) + return std::abs(nSigmaTOF); + return nSigmaTPC; + } + + // Reconstruct the candidate 4-momentum from two daughter tracks + template + ROOT::Math::PxPyPzMVector recMother(const T& track1, const T& track2, float masstrack1, float masstrack2) + { + ROOT::Math::PxPyPzMVector daughter1(track1.px(), track1.py(), track1.pz(), masstrack1); // set the daughter1 4-momentum + ROOT::Math::PxPyPzMVector daughter2(track2.px(), track2.py(), track2.pz(), masstrack2); // set the daughter2 4-momentum + ROOT::Math::PxPyPzMVector mother = daughter1 + daughter2; // calculate the mother 4-momentum + + return mother; + } + + template + void fillCandidateTree(const T1& collision, const T2& track1, const T2& track2, float masstrack1, float masstrack2) + { + auto tpctofPi1 = combineNSigma(track1); + auto tpctofKa1 = combineNSigma(track1); + auto tpctofPi2 = combineNSigma(track2); + auto tpctofKa2 = combineNSigma(track2); + + ROOT::Math::PxPyPzMVector recCandidate = recMother(track1, track2, masstrack1, masstrack2); + + if (downSampleBkgFactor < 1.) { + float pseudoRndm = track1.pt() * 1000. - static_cast(track1.pt() * 1000); + if (recCandidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) + return; + } + + bool isPhi = false; + if constexpr (isMC) { + if (track1.has_mcParticle() && track2.has_mcParticle()) { + auto mcTrack1 = track1.template mcParticle_as(); + auto mcTrack2 = track2.template mcParticle_as(); + + auto mothersOfMcTrack1 = mcTrack1.template mothers_as(); + auto mothersOfMcTrack2 = mcTrack2.template mothers_as(); + + for (const auto& motherOfMcTrack1 : mothersOfMcTrack1) { + for (const auto& motherOfMcTrack2 : mothersOfMcTrack2) { + if (mcTrack1.pdgCode() == PDG_t::kKPlus && mcTrack2.pdgCode() == PDG_t::kKMinus && + motherOfMcTrack1.pdgCode() == motherOfMcTrack2.pdgCode() && motherOfMcTrack1.pdgCode() == o2::constants::physics::Pdg::kPhi) { + isPhi = true; + break; + } + } + } + } + + if (fillOnlySignal && !isPhi) + return; // Skip filling if only signal is requested and not a phi candidate + if (fillOnlyBackground && isPhi) + return; // Skip filling if only background is requested and a phi candidate + } + + /*isPhi = (mcTrack1.pdgCode() == PDG_t::kKPlus && mcTrack2.pdgCode() == PDG_t::kKMinus && + motherOfMcTrack1.pdgCode() == motherOfMcTrack2.pdgCode() && motherOfMcTrack1.pdgCode() == o2::constants::physics::Pdg::kPhi); + }*/ + + resoMLCandidates(collision.centFT0M(), + track1.pt(), track1.p(), track1.phi(), track1.eta(), track1.rapidity(masstrack1), track1.dcaXY(), track1.dcaZ(), + track1.tpcNSigmaPi(), track1.tpcNSigmaKa(), track1.tofNSigmaPi(), track1.tofNSigmaKa(), tpctofPi1, tpctofKa1, + track2.pt(), track2.p(), track2.phi(), track2.eta(), track2.rapidity(masstrack2), track2.dcaXY(), track2.dcaZ(), + track2.tpcNSigmaPi(), track2.tpcNSigmaKa(), track2.tofNSigmaPi(), track2.tofNSigmaKa(), tpctofPi2, tpctofKa2, + recCandidate.M(), recCandidate.Pt(), recCandidate.P(), recCandidate.Phi(), + recCandidate.Eta(), recCandidate.Rapidity(), track1.sign() + track2.sign(), isPhi); + } + + void processData(SelCollisions::iterator const& collision, FullTracks const&) + { + auto posThisColl = posTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto negThisColl = negTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + + for (const auto& track1 : posThisColl) { + for (const auto& track2 : negThisColl) { + if (track1.globalIndex() == track2.globalIndex()) + continue; // condition to avoid double counting of pair + + // Fill the ResoMLCandidates table with candidates in Data + fillCandidateTree(collision, track1, track2, massKa, massKa); + } + } + } + + PROCESS_SWITCH(resonanceTreeCreator, processData, "Fill ResoMLCandidates in Data", true); + + void processMC(SimCollisions::iterator const& collision, FullMCTracks const&, aod::McParticles const&) + { + auto posThisColl = posMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto negThisColl = negMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + + for (const auto& track1 : posThisColl) { + for (const auto& track2 : negThisColl) { + if (track1.globalIndex() == track2.globalIndex()) + continue; // condition to avoid double counting of pair + + // Fill the ResoMLCandidates table with candidates in MC + fillCandidateTree(collision, track1, track2, massKa, massKa); + } + } + } + + PROCESS_SWITCH(resonanceTreeCreator, processMC, "Fill ResoMLCandidates in MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} From 453532d023fd27c0f9d18d81fe3ef941455914a6 Mon Sep 17 00:00:00 2001 From: Stefano Cannito Date: Tue, 8 Jul 2025 14:14:54 +0200 Subject: [PATCH 2/4] Revert "First commit for ResonanceTreeCreator" This reverts commit 40344b5a4a79be8cb97331cb9bb3324371893bc0. --- PWGLF/TableProducer/Resonances/CMakeLists.txt | 5 - .../Resonances/resonanceTreeCreator.cxx | 334 ------------------ 2 files changed, 339 deletions(-) delete mode 100644 PWGLF/TableProducer/Resonances/resonanceTreeCreator.cxx diff --git a/PWGLF/TableProducer/Resonances/CMakeLists.txt b/PWGLF/TableProducer/Resonances/CMakeLists.txt index ce811fdcc97..79b69b5b071 100644 --- a/PWGLF/TableProducer/Resonances/CMakeLists.txt +++ b/PWGLF/TableProducer/Resonances/CMakeLists.txt @@ -49,8 +49,3 @@ o2physics_add_dpl_workflow(heptaquarktable SOURCES HeptaQuarktable.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsVertexing COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(resonance-tree-creator - SOURCES resonanceTreeCreator.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsBase - COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/PWGLF/TableProducer/Resonances/resonanceTreeCreator.cxx b/PWGLF/TableProducer/Resonances/resonanceTreeCreator.cxx deleted file mode 100644 index 3275e3e00b4..00000000000 --- a/PWGLF/TableProducer/Resonances/resonanceTreeCreator.cxx +++ /dev/null @@ -1,334 +0,0 @@ -// Copyright 2019-2020 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 resonanceTreeCreator.cxx -/// \brief Produces a TTree with machine learning variables for resonances in the LF group -/// \author Stefano Cannito (stefano.cannito@cern.ch) - -#include "Common/DataModel/EventSelection.h" - -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -// #include "PWGLF/DataModel/LFResonanceMLTables.h" -#include "PWGLF/DataModel/mcCentrality.h" -#include "PWGLF/Utils/inelGt.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "ReconstructionDataFormats/Track.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -namespace o2::aod -{ -namespace resomlcandidates -{ -// Multiplicity class -DECLARE_SOA_COLUMN(MultClass, multClass, float); //! Event multiplicity class -// Daughter 1 -DECLARE_SOA_COLUMN(PtDaughter1, ptdaughter1, float); //! Transverse momentum of daughter1 (GeV/c) -DECLARE_SOA_COLUMN(PDaughter1, pdaughter1, float); //! Momentum of daughter1 (GeV/c) -DECLARE_SOA_COLUMN(PhiDaughter1, phiDaughter1, float); //! Azimuthal angle of daughter1 (rad) -DECLARE_SOA_COLUMN(EtaDaughter1, etaDaughter1, float); //! Pseudorapidity of daughter1 -DECLARE_SOA_COLUMN(YDaughter1, yDaughter1, float); //! Rapidity of daughter1 -DECLARE_SOA_COLUMN(DCAxyDaughter1, dcaDaughter1, float); //! DCA of daughter1 to primary vertex (cm) -DECLARE_SOA_COLUMN(DCAzDaughter1, dcaZDaughter1, float); //! DCA of daughter1 to primary vertex in z (cm) -DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); //! TPC Nsigma separation for daughter1 with pion mass hypothesis -DECLARE_SOA_COLUMN(NSigTpcKa1, nSigTpcKa1, float); //! TPC Nsigma separation for daughter1 with kaon mass hypothesis -DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF Nsigma separation for daughter1 with pion mass hypothesis -DECLARE_SOA_COLUMN(NSigTofKa1, nSigTofKa1, float); //! TOF Nsigma separation for daughter1 with kaon mass hypothesis -DECLARE_SOA_COLUMN(NSigTpcTofPi1, nSigTpcTofPi1, float); //! TPC and TOF combined Nsigma separation for daughter1 with pion mass hypothesis -DECLARE_SOA_COLUMN(NSigTpcTofKa1, nSigTpcTofKa1, float); //! TPC and TOF combined Nsigma separation for daughter1 with kaon mass hypothesis -// Daughter 2 -DECLARE_SOA_COLUMN(PtDaughter2, ptdaughter2, float); //! Transverse momentum of daughter2 (GeV/c) -DECLARE_SOA_COLUMN(PDaughter2, pdaughter2, float); //! Momentum of daughter2 (in GeV/c) -DECLARE_SOA_COLUMN(PhiDaughter2, phiDaughter2, float); //! Azimuthal angle of daughter2 (rad) -DECLARE_SOA_COLUMN(EtaDaughter2, etaDaughter2, float); //! Pseudorapidity of daughter2 -DECLARE_SOA_COLUMN(YDaughter2, yDaughter2, float); //! Rapidity of daughter2 -DECLARE_SOA_COLUMN(DCAxyDaughter2, dcaDaughter2, float); //! DCA of daughter2 to primary vertex (cm) -DECLARE_SOA_COLUMN(DCAzDaughter2, dcaZDaughter2, float); //! DCA of daughter2 to primary vertex in z (cm) -DECLARE_SOA_COLUMN(NSigTpcPi2, nSigTpcPi2, float); //! TPC Nsigma separation for daughter2 with pion mass hypothesis -DECLARE_SOA_COLUMN(NSigTpcKa2, nSigTpcKa2, float); //! TPC Nsigma separation for daughter2 with kaon mass hypothesis -DECLARE_SOA_COLUMN(NSigTofPi2, nSigTofPi2, float); //! TOF Nsigma separation for daughter2 with pion mass hypothesis -DECLARE_SOA_COLUMN(NSigTofKa2, nSigTofKa2, float); //! TOF Nsigma separation for daughter2 with kaon mass hypothesis -DECLARE_SOA_COLUMN(NSigTpcTofPi2, nSigTpcTofPi2, float); //! TPC and TOF combined Nsigma separation for daughter2 with pion mass hypothesis -DECLARE_SOA_COLUMN(NSigTpcTofKa2, nSigTpcTofKa2, float); //! TPC and TOF combined Nsigma separation for daughter2 with kaon mass hypothesis -// Candidate -DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) -DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) -DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) -DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate -DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate -DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate -DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! Sign of the candidate -DECLARE_SOA_COLUMN(IsPhi, isPhi, bool); //! Flag to indicate if the candidate is a phi meson -} // namespace resomlcandidates - -DECLARE_SOA_TABLE(ResoMLCandidates, "AOD", "RESOMLCANDIDATES", - resomlcandidates::MultClass, - resomlcandidates::PtDaughter1, - resomlcandidates::PDaughter1, - resomlcandidates::PhiDaughter1, - resomlcandidates::EtaDaughter1, - resomlcandidates::YDaughter1, - resomlcandidates::DCAxyDaughter1, - resomlcandidates::DCAzDaughter1, - resomlcandidates::NSigTpcPi1, - resomlcandidates::NSigTpcKa1, - resomlcandidates::NSigTofPi1, - resomlcandidates::NSigTofKa1, - resomlcandidates::NSigTpcTofPi1, - resomlcandidates::NSigTpcTofKa1, - resomlcandidates::PtDaughter2, - resomlcandidates::PDaughter2, - resomlcandidates::PhiDaughter2, - resomlcandidates::EtaDaughter2, - resomlcandidates::YDaughter2, - resomlcandidates::DCAxyDaughter2, - resomlcandidates::DCAzDaughter2, - resomlcandidates::NSigTpcPi2, - resomlcandidates::NSigTpcKa2, - resomlcandidates::NSigTofPi2, - resomlcandidates::NSigTofKa2, - resomlcandidates::NSigTpcTofPi2, - resomlcandidates::NSigTpcTofKa2, - resomlcandidates::M, - resomlcandidates::Pt, - resomlcandidates::P, - resomlcandidates::Phi, - resomlcandidates::Eta, - resomlcandidates::Y, - resomlcandidates::Sign, - resomlcandidates::IsPhi); - -namespace resomlselection -{ -DECLARE_SOA_COLUMN(PhiBDTScore, gammaBDTScore, float); -} // namespace resomlselection - -DECLARE_SOA_TABLE(ResoPhiMLSelection, "AOD", "RESOPHIMLSELECTION", - resomlselection::PhiBDTScore); -} // namespace o2::aod - -struct resonanceTreeCreator { - // Production of the TTree - Produces resoMLCandidates; - - // Configurables for track selection - Configurable cfgCutCharge{"cfgCutCharge", 0.0f, "Cut on the signed transverse momentum to select positive or negative tracks"}; - - // Configurables for production of training samples - Configurable fillOnlySignal{"fillOnlySignal", false, "Flag to fill derived tables with signal for ML trainings"}; - Configurable fillOnlyBackground{"fillOnlyBackground", false, "Flag to fill derived tables with background for ML trainings"}; - Configurable downSampleBkgFactor{"downSampleBkgFactor", 0.5f, "Fraction of background candidates to keep for ML trainings"}; - Configurable ptMaxForDownSample{"ptMaxForDownSample", 10.0f, "Maximum pt for the application of the downsampling factor"}; - - // Defining the type of the collisions for data and MC - using SelCollisions = soa::Join; - using SimCollisions = soa::Join; - - // Defining the type of the tracks for data and MC - using FullTracks = soa::Join; - using FullMCTracks = soa::Join; - - Partition posTracks = aod::track::signed1Pt > cfgCutCharge; - Partition negTracks = aod::track::signed1Pt < cfgCutCharge; - - Partition posMCTracks = aod::track::signed1Pt > cfgCutCharge; - Partition negMCTracks = aod::track::signed1Pt < cfgCutCharge; - - // Cache for the tracks - SliceCache cache; - - // Necessary to flag INEL>0 events in GenMC - Service pdgDB; - - enum ParticleType { - Pi, - Ka, - Pr - }; - - // Constants - double massPi = o2::constants::physics::MassPiPlus; - double massKa = o2::constants::physics::MassKPlus; - - void init(InitContext&) - { - } - - // Combine Nsigma values from TPC and TOF - template - float combineNSigma(const T& track) - { - float nSigmaTPC, nSigmaTOF; - switch (massHypo) { - case Pi: - nSigmaTPC = track.tpcNSigmaPi(); - nSigmaTOF = track.tofNSigmaPi(); - break; - case Ka: - nSigmaTPC = track.tpcNSigmaKa(); - nSigmaTOF = track.tofNSigmaKa(); - break; - case Pr: - nSigmaTPC = track.tpcNSigmaPr(); - nSigmaTOF = track.tofNSigmaPr(); - break; - default: - break; - } - - static constexpr float defaultNSigmaTolerance = .1f; - static constexpr float defaultNSigma = -999.f + defaultNSigmaTolerance; - - if (nSigmaTPC > defaultNSigma && nSigmaTOF > defaultNSigma) - return std::sqrt(0.5f * std::pow(nSigmaTPC, 2) + std::pow(nSigmaTOF, 2)); - if (nSigmaTPC > defaultNSigma) - return std::abs(nSigmaTPC); - if (nSigmaTOF > defaultNSigma) - return std::abs(nSigmaTOF); - return nSigmaTPC; - } - - // Reconstruct the candidate 4-momentum from two daughter tracks - template - ROOT::Math::PxPyPzMVector recMother(const T& track1, const T& track2, float masstrack1, float masstrack2) - { - ROOT::Math::PxPyPzMVector daughter1(track1.px(), track1.py(), track1.pz(), masstrack1); // set the daughter1 4-momentum - ROOT::Math::PxPyPzMVector daughter2(track2.px(), track2.py(), track2.pz(), masstrack2); // set the daughter2 4-momentum - ROOT::Math::PxPyPzMVector mother = daughter1 + daughter2; // calculate the mother 4-momentum - - return mother; - } - - template - void fillCandidateTree(const T1& collision, const T2& track1, const T2& track2, float masstrack1, float masstrack2) - { - auto tpctofPi1 = combineNSigma(track1); - auto tpctofKa1 = combineNSigma(track1); - auto tpctofPi2 = combineNSigma(track2); - auto tpctofKa2 = combineNSigma(track2); - - ROOT::Math::PxPyPzMVector recCandidate = recMother(track1, track2, masstrack1, masstrack2); - - if (downSampleBkgFactor < 1.) { - float pseudoRndm = track1.pt() * 1000. - static_cast(track1.pt() * 1000); - if (recCandidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) - return; - } - - bool isPhi = false; - if constexpr (isMC) { - if (track1.has_mcParticle() && track2.has_mcParticle()) { - auto mcTrack1 = track1.template mcParticle_as(); - auto mcTrack2 = track2.template mcParticle_as(); - - auto mothersOfMcTrack1 = mcTrack1.template mothers_as(); - auto mothersOfMcTrack2 = mcTrack2.template mothers_as(); - - for (const auto& motherOfMcTrack1 : mothersOfMcTrack1) { - for (const auto& motherOfMcTrack2 : mothersOfMcTrack2) { - if (mcTrack1.pdgCode() == PDG_t::kKPlus && mcTrack2.pdgCode() == PDG_t::kKMinus && - motherOfMcTrack1.pdgCode() == motherOfMcTrack2.pdgCode() && motherOfMcTrack1.pdgCode() == o2::constants::physics::Pdg::kPhi) { - isPhi = true; - break; - } - } - } - } - - if (fillOnlySignal && !isPhi) - return; // Skip filling if only signal is requested and not a phi candidate - if (fillOnlyBackground && isPhi) - return; // Skip filling if only background is requested and a phi candidate - } - - /*isPhi = (mcTrack1.pdgCode() == PDG_t::kKPlus && mcTrack2.pdgCode() == PDG_t::kKMinus && - motherOfMcTrack1.pdgCode() == motherOfMcTrack2.pdgCode() && motherOfMcTrack1.pdgCode() == o2::constants::physics::Pdg::kPhi); - }*/ - - resoMLCandidates(collision.centFT0M(), - track1.pt(), track1.p(), track1.phi(), track1.eta(), track1.rapidity(masstrack1), track1.dcaXY(), track1.dcaZ(), - track1.tpcNSigmaPi(), track1.tpcNSigmaKa(), track1.tofNSigmaPi(), track1.tofNSigmaKa(), tpctofPi1, tpctofKa1, - track2.pt(), track2.p(), track2.phi(), track2.eta(), track2.rapidity(masstrack2), track2.dcaXY(), track2.dcaZ(), - track2.tpcNSigmaPi(), track2.tpcNSigmaKa(), track2.tofNSigmaPi(), track2.tofNSigmaKa(), tpctofPi2, tpctofKa2, - recCandidate.M(), recCandidate.Pt(), recCandidate.P(), recCandidate.Phi(), - recCandidate.Eta(), recCandidate.Rapidity(), track1.sign() + track2.sign(), isPhi); - } - - void processData(SelCollisions::iterator const& collision, FullTracks const&) - { - auto posThisColl = posTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - auto negThisColl = negTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - - for (const auto& track1 : posThisColl) { - for (const auto& track2 : negThisColl) { - if (track1.globalIndex() == track2.globalIndex()) - continue; // condition to avoid double counting of pair - - // Fill the ResoMLCandidates table with candidates in Data - fillCandidateTree(collision, track1, track2, massKa, massKa); - } - } - } - - PROCESS_SWITCH(resonanceTreeCreator, processData, "Fill ResoMLCandidates in Data", true); - - void processMC(SimCollisions::iterator const& collision, FullMCTracks const&, aod::McParticles const&) - { - auto posThisColl = posMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - auto negThisColl = negMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - - for (const auto& track1 : posThisColl) { - for (const auto& track2 : negThisColl) { - if (track1.globalIndex() == track2.globalIndex()) - continue; // condition to avoid double counting of pair - - // Fill the ResoMLCandidates table with candidates in MC - fillCandidateTree(collision, track1, track2, massKa, massKa); - } - } - } - - PROCESS_SWITCH(resonanceTreeCreator, processMC, "Fill ResoMLCandidates in MC", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{adaptAnalysisTask(cfgc)}; -} From ceeb8edb4f9de5e0547e66d447cc3926f405b962 Mon Sep 17 00:00:00 2001 From: Stefano Cannito Date: Tue, 8 Jul 2025 14:51:24 +0200 Subject: [PATCH 3/4] Safeguard check on efficiencies --- .../Tasks/Strangeness/phik0shortanalysis.cxx | 48 ++++++++++++++++--- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/phik0shortanalysis.cxx b/PWGLF/Tasks/Strangeness/phik0shortanalysis.cxx index 3a82e3c1c97..a272144a302 100644 --- a/PWGLF/Tasks/Strangeness/phik0shortanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/phik0shortanalysis.cxx @@ -2515,7 +2515,13 @@ struct Phik0shortanalysis { isCountedPhi = true; } - float weightPhi = applyEfficiency ? 1.0f / (effMapPhi->Interpolate(multiplicity, recPhi.Pt(), recPhi.Rapidity())) : 1.0f; + float efficiencyPhi = 1.0f; + if (applyEfficiency) { + efficiencyPhi = effMapPhi->Interpolate(multiplicity, recPhi.Pt(), recPhi.Rapidity()); + if (efficiencyPhi == 0) + efficiencyPhi = 1.0f; + } + float weightPhi = applyEfficiency ? 1.0f / efficiencyPhi : 1.0f; dataPhiHist.fill(HIST("h3PhiDataNewProc"), multiplicity, recPhi.Pt(), recPhi.M(), weightPhi); // V0 already reconstructed by the builder @@ -2543,7 +2549,13 @@ struct Phik0shortanalysis { if (std::abs(v0.yK0Short()) > cfgYAcceptance) continue; - float weightPhiK0S = applyEfficiency ? 1.0f / (effMapPhi->Interpolate(multiplicity, recPhi.Pt(), recPhi.Rapidity()) * effMapK0S->Interpolate(multiplicity, v0.pt(), v0.yK0Short())) : 1.0f; + float efficiencyPhiK0S = 1.0f; + if (applyEfficiency) { + efficiencyPhiK0S = effMapPhi->Interpolate(multiplicity, recPhi.Pt(), recPhi.Rapidity()) * effMapK0S->Interpolate(multiplicity, v0.pt(), v0.yK0Short()); + if (efficiencyPhiK0S == 0) + efficiencyPhiK0S = 1.0f; + } + float weightPhiK0S = applyEfficiency ? 1.0f / efficiencyPhiK0S : 1.0f; dataPhiK0SHist.fill(HIST("h5PhiK0SDataNewProc"), v0.yK0Short() - recPhi.Rapidity(), multiplicity, v0.pt(), v0.mK0Short(), recPhi.M(), weightPhiK0S); } @@ -2559,7 +2571,13 @@ struct Phik0shortanalysis { float nSigmaTOFPi = (track.hasTOF() ? track.tofNSigmaPi() : -999); - float weightPhiPion = applyEfficiency ? 1.0f / (effMapPhi->Interpolate(multiplicity, recPhi.Pt(), recPhi.Rapidity()) * effMapPion->Interpolate(multiplicity, track.pt(), track.rapidity(massPi))) : 1.0f; + float efficiencyPhiPion = 1.0f; + if (applyEfficiency) { + efficiencyPhiPion = effMapPhi->Interpolate(multiplicity, recPhi.Pt(), recPhi.Rapidity()) * effMapPion->Interpolate(multiplicity, track.pt(), track.rapidity(massPi)); + if (efficiencyPhiPion == 0) + efficiencyPhiPion = 1.0f; + } + float weightPhiPion = applyEfficiency ? 1.0f / efficiencyPhiPion : 1.0f; dataPhiPionHist.fill(HIST("h6PhiPiDataNewProc"), track.rapidity(massPi) - recPhi.Rapidity(), multiplicity, track.pt(), track.tpcNSigmaPi(), nSigmaTOFPi, recPhi.M(), weightPhiPion); } } @@ -2615,7 +2633,13 @@ struct Phik0shortanalysis { isCountedPhi = true; } - float weightPhi = applyEfficiency ? 1.0f / (effMapPhi->Interpolate(genmultiplicity, recPhi.Pt(), recPhi.Rapidity())) : 1.0f; + float efficiencyPhi = 1.0f; + if (applyEfficiency) { + efficiencyPhi = effMapPhi->Interpolate(genmultiplicity, recPhi.Pt(), recPhi.Rapidity()); + if (efficiencyPhi == 0) + efficiencyPhi = 1.0f; + } + float weightPhi = applyEfficiency ? 1.0f / efficiencyPhi : 1.0f; closureMCPhiHist.fill(HIST("h3PhiMCClosureNewProc"), genmultiplicity, recPhi.Pt(), recPhi.M(), weightPhi); // V0 already reconstructed by the builder @@ -2639,7 +2663,13 @@ struct Phik0shortanalysis { if (std::abs(v0.yK0Short()) > cfgYAcceptance) continue; - float weightPhiK0S = applyEfficiency ? 1.0f / (effMapPhi->Interpolate(genmultiplicity, recPhi.Pt(), recPhi.Rapidity()) * effMapK0S->Interpolate(genmultiplicity, v0.pt(), v0.yK0Short())) : 1.0f; + float efficiencyPhiK0S = 1.0f; + if (applyEfficiency) { + efficiencyPhiK0S = effMapPhi->Interpolate(genmultiplicity, recPhi.Pt(), recPhi.Rapidity()) * effMapK0S->Interpolate(genmultiplicity, v0.pt(), v0.yK0Short()); + if (efficiencyPhiK0S == 0) + efficiencyPhiK0S = 1.0f; + } + float weightPhiK0S = applyEfficiency ? 1.0f / efficiencyPhiK0S : 1.0f; closureMCPhiK0SHist.fill(HIST("h5PhiK0SMCClosureNewProc"), v0.yK0Short() - recPhi.Rapidity(), genmultiplicity, v0.pt(), v0.mK0Short(), recPhi.M(), weightPhiK0S); } @@ -2661,7 +2691,13 @@ struct Phik0shortanalysis { float nSigmaTOFPi = (track.hasTOF() ? track.tofNSigmaPi() : -999); - float weightPhiPion = applyEfficiency ? 1.0f / (effMapPhi->Interpolate(genmultiplicity, recPhi.Pt(), recPhi.Rapidity()) * effMapPion->Interpolate(genmultiplicity, track.pt(), track.rapidity(massPi))) : 1.0f; + float efficiencyPhiPion = 1.0f; + if (applyEfficiency) { + efficiencyPhiPion = effMapPhi->Interpolate(genmultiplicity, recPhi.Pt(), recPhi.Rapidity()) * effMapPion->Interpolate(genmultiplicity, track.pt(), track.rapidity(massPi)); + if (efficiencyPhiPion == 0) + efficiencyPhiPion = 1.0f; + } + float weightPhiPion = applyEfficiency ? 1.0f / efficiencyPhiPion : 1.0f; closureMCPhiPionHist.fill(HIST("h6PhiPiMCClosureNewProc"), track.rapidity(massPi) - recPhi.Rapidity(), genmultiplicity, track.pt(), track.tpcNSigmaPi(), nSigmaTOFPi, recPhi.M(), weightPhiPion); } } From 2f563ad48ced7c53bdeef4bc2721249c0cd98765 Mon Sep 17 00:00:00 2001 From: Stefano Cannito Date: Tue, 8 Jul 2025 15:29:07 +0200 Subject: [PATCH 4/4] Polished selection of phi's daughter track and pion track candidates --- .../Tasks/Strangeness/phik0shortanalysis.cxx | 35 ++++++------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/phik0shortanalysis.cxx b/PWGLF/Tasks/Strangeness/phik0shortanalysis.cxx index a272144a302..e3f1c0dcdae 100644 --- a/PWGLF/Tasks/Strangeness/phik0shortanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/phik0shortanalysis.cxx @@ -91,7 +91,6 @@ struct Phik0shortanalysis { // Configurables for track selection (not necessarily common for trigger and the two associated particles) struct : ConfigurableGroup { Configurable cfgCutCharge{"cfgCutCharge", 0.0f, "Cut on charge"}; - Configurable cfgPrimaryTrack{"cfgPrimaryTrack", false, "Primary track selection"}; Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; Configurable cfgPVContributor{"cfgPVContributor", true, "PV contributor track selection"}; Configurable cMinKaonPtcut{"cMinKaonPtcut", 0.15f, "Track minimum pt cut"}; @@ -115,9 +114,9 @@ struct Phik0shortanalysis { Configurable nSigmaCutCombinedKa{"nSigmaCutCombinedKa", 3.0f, "Value of the TOF Nsigma cut for Kaons"}; Configurable nSigmaCutTPCPion{"nSigmaCutTPCPion", 4.0f, "Value of the TPC Nsigma cut for Pions"}; - Configurable cMinPionPtcut{"cMinPionPtcut", 0.3f, "Track minimum pt cut"}; + Configurable cMinPionPtcut{"cMinPionPtcut", 0.2f, "Track minimum pt cut"}; Configurable minTPCnClsFound{"minTPCnClsFound", 70, "min number of found TPC clusters"}; - Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 80, "min number of TPC crossed rows"}; + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70, "min number of TPC crossed rows"}; Configurable maxChi2TPC{"maxChi2TPC", 4.0f, "max chi2 per cluster TPC"}; Configurable minITSnCls{"minITSnCls", 4, "min number of ITS clusters"}; Configurable maxChi2ITS{"maxChi2ITS", 36.0f, "max chi2 per cluster ITS"}; @@ -724,10 +723,8 @@ struct Phik0shortanalysis { // Topological track selection template - bool selectionTrackResonance(const T& track, bool isQA) + bool selectionTrackResonance(const T& track, bool doQA) { - if (trackConfigs.cfgPrimaryTrack && !track.isPrimaryTrack()) - return false; if (trackConfigs.cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) return false; if (trackConfigs.cfgPVContributor && !track.isPVContributor()) @@ -738,10 +735,8 @@ struct Phik0shortanalysis { if (track.pt() < trackConfigs.cMinKaonPtcut) return false; - if (std::abs(track.eta()) > trackConfigs.etaMax) - return false; - if (isQA) { + if (doQA) { if constexpr (!isMC) { dataPhiHist.fill(HIST("h2DauTracksPhiDCAxyPreCutData"), track.pt(), track.dcaXY()); dataPhiHist.fill(HIST("h2DauTracksPhiDCAzPreCutData"), track.pt(), track.dcaZ()); @@ -752,7 +747,7 @@ struct Phik0shortanalysis { } if (std::abs(track.dcaXY()) > trackConfigs.cMaxDCArToPV1Phi + (trackConfigs.cMaxDCArToPV2Phi / std::pow(track.pt(), trackConfigs.cMaxDCArToPV3Phi))) return false; - if (isQA) { + if (doQA) { if constexpr (!isMC) { dataPhiHist.fill(HIST("h2DauTracksPhiDCAxyPostCutData"), track.pt(), track.dcaXY()); dataPhiHist.fill(HIST("h2DauTracksPhiDCAzPostCutData"), track.pt(), track.dcaZ()); @@ -802,35 +797,25 @@ struct Phik0shortanalysis { // Topological selection for pions template - bool selectionPion(const T& track, bool isQA) + bool selectionPion(const T& track, bool doQA) { - if (!track.hasITS()) - return false; - if (track.itsNCls() < trackConfigs.minITSnCls) - return false; - if (track.itsChi2NCl() > trackConfigs.maxChi2ITS) + if (!track.isGlobalTrackWoDCA()) return false; - if (!track.hasTPC()) + if (track.itsNCls() < trackConfigs.minITSnCls) return false; if (track.tpcNClsFound() < trackConfigs.minTPCnClsFound) return false; - if (track.tpcNClsCrossedRows() < trackConfigs.minNCrossedRowsTPC) - return false; - if (track.tpcChi2NCl() > trackConfigs.maxChi2TPC) - return false; if (track.pt() < trackConfigs.cMinPionPtcut) return false; - if (std::abs(track.eta()) > trackConfigs.etaMax) - return false; if constexpr (isTOFChecked) { if (track.pt() >= trackConfigs.pTToUseTOF && !track.hasTOF()) return false; } - if (isQA) { + if (doQA) { if constexpr (!isMC) { dataPionHist.fill(HIST("h2TracksPiDCAxyPreCutData"), track.pt(), track.dcaXY()); dataPionHist.fill(HIST("h2TracksPiDCAzPreCutData"), track.pt(), track.dcaZ()); @@ -841,7 +826,7 @@ struct Phik0shortanalysis { } if (std::abs(track.dcaXY()) > trackConfigs.cMaxDCArToPV1Pion + (trackConfigs.cMaxDCArToPV2Pion / std::pow(track.pt(), trackConfigs.cMaxDCArToPV3Pion))) return false; - if (isQA) { + if (doQA) { if constexpr (!isMC) { dataPionHist.fill(HIST("h2TracksPiDCAxyPostCutData"), track.pt(), track.dcaXY()); dataPionHist.fill(HIST("h2TracksPiDCAzPostCutData"), track.pt(), track.dcaZ());