From c6afeec8164cc1271f3108b5bb33fcc612be8734 Mon Sep 17 00:00:00 2001 From: apalasciano Date: Wed, 1 Apr 2026 21:04:56 +0200 Subject: [PATCH] [PWGHF] test pp channel for eta_c --- PWGHF/D2H/DataModel/ReducedDataModel.h | 123 +++---- PWGHF/D2H/TableProducer/CMakeLists.txt | 5 + .../dataCreatorHiddenCharmReduced.cxx | 317 ++++++++++++++++++ PWGHF/D2H/Tasks/CMakeLists.txt | 5 + PWGHF/D2H/Tasks/taskHiddenCharm.cxx | 146 ++++++++ 5 files changed, 538 insertions(+), 58 deletions(-) create mode 100644 PWGHF/D2H/TableProducer/dataCreatorHiddenCharmReduced.cxx create mode 100644 PWGHF/D2H/Tasks/taskHiddenCharm.cxx diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index d70597c8678..7dfaa27dee6 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -196,6 +196,7 @@ DECLARE_SOA_COLUMN(TpcNClsCrossedRowsProngMin, tpcNClsCrossedRowsProngMin, int); DECLARE_SOA_COLUMN(TpcChi2NClProngMax, tpcChi2NClProngMax, float); //! maximum value of TPC chi2 for the decay daughter tracks DECLARE_SOA_COLUMN(PtProngMin, ptProngMin, float); //! minimum value of transverse momentum for the decay daughter tracks DECLARE_SOA_COLUMN(AbsEtaProngMin, absEtaProngMin, float); //! minimum value of absolute pseudorapidity for the decay daughter tracks +DECLARE_SOA_COLUMN(TrackType, tracktype, uint8_t); //! particle type according to PID selection (pion, kaon, proton) // dynamic columns DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! transverse momentum @@ -846,11 +847,6 @@ DECLARE_SOA_TABLE(HfRedLbLcMls, "AOD", "HFREDLBLCML", //! Table with ML scores f using HfRedCandLb = soa::Join; -namespace hf_cand_mc_flag -{ -DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); //! reconstruction level -} - namespace hf_b0_mc { // MC Rec @@ -878,9 +874,9 @@ DECLARE_SOA_COLUMN(PdgCodeProng3, pdgCodeProng3, int); //! Pdg code DECLARE_SOA_TABLE(HfMcRecRedDpPis, "AOD", "HFMCRECREDDPPI", //! Table with reconstructed MC information on DPi(<-B0) pairs for reduced workflow hf_cand_b0_reduced::Prong0Id, hf_cand_b0_reduced::Prong1Id, - hf_cand_mc_flag::FlagMcMatchRec, - hf_cand_mc_flag::FlagWrongCollision, - hf_cand_mc_flag::DebugMcRec, + hf_cand_b0::FlagMcMatchRec, + hf_cand_b0::FlagWrongCollision, + hf_cand_b0::DebugMcRec, hf_b0_mc::PtMother); // try with extended table ? @@ -898,17 +894,17 @@ DECLARE_SOA_TABLE(HfMcCheckDpPis, "AOD", "HFMCCHECKDPPI", //! Table with reconst DECLARE_SOA_TABLE(HfMcRecRedDStarPis, "AOD", "HFMCRECREDDSTPI", //! Table with reconstructed MC information on DStarPi pairs for reduced workflow hf_cand_b0_reduced::ProngD0Id, hf_cand_b0_reduced::ProngBachPiId, - hf_cand_mc_flag::FlagMcMatchRec, - hf_cand_mc_flag::FlagWrongCollision, - hf_cand_mc_flag::DebugMcRec, + hf_cand_b0::FlagMcMatchRec, + hf_cand_b0::FlagWrongCollision, + hf_cand_b0::DebugMcRec, hf_b0_mc::PtMother); // Table with same size as HFCANDB0 DECLARE_SOA_TABLE(HfMcRecRedB0s, "AOD", "HFMCRECREDB0", //! Reconstruction-level MC information on B0 candidates for reduced workflow - hf_cand_mc_flag::FlagMcMatchRec, - hf_cand_mc_flag::FlagMcDecayChanRec, - hf_cand_mc_flag::FlagWrongCollision, - hf_cand_mc_flag::DebugMcRec, + hf_cand_b0::FlagMcMatchRec, + hf_cand_b0::FlagMcDecayChanRec, + hf_cand_b0::FlagWrongCollision, + hf_cand_b0::DebugMcRec, hf_b0_mc::PtMother); DECLARE_SOA_TABLE(HfMcCheckB0s, "AOD", "HFMCCHECKB0", //! Table with reconstructed MC information on B0 candidates for MC checks in reduced workflow @@ -921,8 +917,8 @@ DECLARE_SOA_TABLE(HfMcCheckB0s, "AOD", "HFMCCHECKB0", //! Table with reconstruct o2::soa::Marker<2>); DECLARE_SOA_TABLE(HfMcGenRedB0s, "AOD", "HFMCGENREDB0", //! Generation-level MC information on B0 candidates for reduced workflow - hf_cand_mc_flag::FlagMcMatchGen, - hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_b0::FlagMcMatchGen, + hf_cand_b0::FlagMcDecayChanRec, hf_b0_mc::PtTrack, hf_b0_mc::YTrack, hf_b0_mc::EtaTrack, @@ -974,19 +970,19 @@ DECLARE_SOA_COLUMN(PdgCodeProng2, pdgCodeProng2, int); //! Pdg code DECLARE_SOA_TABLE(HfMcRecRedD0Pis, "AOD", "HFMCRECREDD0PI", //! Table with reconstructed MC information on D0Pi(<-B+) pairs for reduced workflow hf_cand_bplus_reduced::Prong0Id, hf_cand_bplus_reduced::Prong1Id, - hf_cand_mc_flag::FlagMcMatchRec, - hf_cand_mc_flag::FlagWrongCollision, - hf_cand_mc_flag::DebugMcRec, + hf_cand_bplus::FlagMcMatchRec, + hf_cand_bplus::FlagWrongCollision, + hf_cand_bplus::DebugMcRec, hf_bplus_mc::PtMother); // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfMcRecRedJPKs, "AOD", "HFMCRECREDJPK", //! Table with reconstructed MC information on J/PsiK(<-B+) pairs for reduced workflow hf_cand_bplus_reduced::JpsiId, hf_cand_bplus_reduced::BachKaId, - hf_cand_mc_flag::FlagMcMatchRec, - hf_cand_mc_flag::FlagMcDecayChanRec, - hf_cand_mc_flag::FlagWrongCollision, - hf_cand_mc_flag::DebugMcRec, + hf_cand_bplus::FlagMcMatchRec, + hf_cand_bplus::FlagMcDecayChanRec, + hf_cand_bplus::FlagWrongCollision, + hf_cand_bplus::DebugMcRec, hf_bplus_mc::PtMother); // DECLARE_SOA_EXTENDED_TABLE_USER(ExTable, Tracks, "EXTABLE", @@ -1000,10 +996,10 @@ DECLARE_SOA_TABLE(HfMcCheckD0Pis, "AOD", "HFMCCHECKD0PI", //! Table with reconst // Table with same size as HFCANDBPLUS DECLARE_SOA_TABLE(HfMcRecRedBps, "AOD", "HFMCRECREDBP", //! Reconstruction-level MC information on B+ candidates for reduced workflow - hf_cand_mc_flag::FlagMcMatchRec, - hf_cand_mc_flag::FlagMcDecayChanRec, - hf_cand_mc_flag::FlagWrongCollision, - hf_cand_mc_flag::DebugMcRec, + hf_cand_bplus::FlagMcMatchRec, + hf_cand_bplus::FlagMcDecayChanRec, + hf_cand_bplus::FlagWrongCollision, + hf_cand_bplus::DebugMcRec, hf_bplus_mc::PtMother); DECLARE_SOA_TABLE(HfMcCheckBps, "AOD", "HFMCCHECKBP", //! Table with reconstructed MC information on B+ candidates for MC checks in reduced workflow @@ -1015,8 +1011,8 @@ DECLARE_SOA_TABLE(HfMcCheckBps, "AOD", "HFMCCHECKBP", //! Table with reconstruct o2::soa::Marker<2>); DECLARE_SOA_TABLE(HfMcGenRedBps, "AOD", "HFMCGENREDBP", //! Generation-level MC information on B+ candidates for reduced workflow - hf_cand_mc_flag::FlagMcMatchGen, - hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_bplus::FlagMcMatchGen, + hf_cand_bplus::FlagMcDecayChanRec, hf_bplus_mc::PtTrack, hf_bplus_mc::YTrack, hf_bplus_mc::EtaTrack, @@ -1075,9 +1071,9 @@ DECLARE_SOA_COLUMN(PdgCodeProng3, pdgCodeProng3, int); //! Pdg code DECLARE_SOA_TABLE(HfMcRecRedDsPis, "AOD", "HFMCRECREDDSPI", //! Table with reconstructed MC information on DsPi(<-Bs) pairs for reduced workflow hf_cand_bs_reduced::Prong0Id, hf_cand_bs_reduced::Prong1Id, - hf_cand_mc_flag::FlagMcMatchRec, - hf_cand_mc_flag::FlagWrongCollision, - hf_cand_mc_flag::DebugMcRec, + hf_cand_bs::FlagMcMatchRec, + hf_cand_bs::FlagWrongCollision, + hf_cand_bs::DebugMcRec, hf_bs_mc::PtMother); // table with results of reconstruction level MC matching @@ -1085,10 +1081,10 @@ DECLARE_SOA_TABLE(HfMcRecRedJPPhis, "AOD", "HFMCRECREDJPPHI", //! Table with rec hf_cand_bs_reduced::JpsiId, hf_cand_bs_reduced::Prong0PhiId, hf_cand_bs_reduced::Prong1PhiId, - hf_cand_mc_flag::FlagMcMatchRec, - hf_cand_mc_flag::FlagMcDecayChanRec, - hf_cand_mc_flag::FlagWrongCollision, - hf_cand_mc_flag::DebugMcRec, + hf_cand_bs::FlagMcMatchRec, + hf_cand_bs::FlagMcDecayChanRec, + hf_cand_bs::FlagWrongCollision, + hf_cand_bs::DebugMcRec, hf_bs_mc::PtMother); // try with extended table ? @@ -1104,10 +1100,10 @@ DECLARE_SOA_TABLE(HfMcCheckDsPis, "AOD", "HFMCCHECKDSPI", //! Table with reconst // Table with same size as HFCANDBS DECLARE_SOA_TABLE(HfMcRecRedBss, "AOD", "HFMCRECREDBS", //! Reconstruction-level MC information on Bs candidates for reduced workflow - hf_cand_mc_flag::FlagMcMatchRec, - hf_cand_mc_flag::FlagMcDecayChanRec, - hf_cand_mc_flag::FlagWrongCollision, - hf_cand_mc_flag::DebugMcRec, + hf_cand_bs::FlagMcMatchRec, + hf_cand_bs::FlagMcDecayChanRec, + hf_cand_bs::FlagWrongCollision, + hf_cand_bs::DebugMcRec, hf_bs_mc::PtMother); DECLARE_SOA_TABLE(HfMcCheckBss, "AOD", "HFMCCHECKBS", //! Table with reconstructed MC information on Bs candidates for MC checks in reduced workflow @@ -1120,8 +1116,8 @@ DECLARE_SOA_TABLE(HfMcCheckBss, "AOD", "HFMCCHECKBS", //! Table with reconstruct o2::soa::Marker<2>); DECLARE_SOA_TABLE(HfMcGenRedBss, "AOD", "HFMCGENREDBS", //! Generation-level MC information on Bs candidates for reduced workflow - hf_cand_mc_flag::FlagMcMatchGen, - hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_bs::FlagMcMatchGen, + hf_cand_bs::FlagMcDecayChanRec, hf_bs_mc::PtTrack, hf_bs_mc::YTrack, hf_bs_mc::EtaTrack, @@ -1177,9 +1173,9 @@ DECLARE_SOA_COLUMN(PdgCodeProng3, pdgCodeProng3, int); //! Pdg code DECLARE_SOA_TABLE(HfMcRecRedLcPis, "AOD", "HFMCRECREDLCPI", //! Table with reconstructed MC information on LcPi(<-Lb) pairs for reduced workflow hf_cand_lb_reduced::Prong0Id, hf_cand_lb_reduced::Prong1Id, - hf_cand_mc_flag::FlagMcMatchRec, - hf_cand_mc_flag::FlagWrongCollision, - hf_cand_mc_flag::DebugMcRec, + hf_cand_lb::FlagMcMatchRec, + hf_cand_lb::FlagWrongCollision, + hf_cand_lb::DebugMcRec, hf_lb_mc::PtMother); DECLARE_SOA_TABLE(HfMcCheckLcPis, "AOD", "HFMCCHECKLCPI", //! Table with reconstructed MC information on LcPi(<-Lb) pairs for MC checks in reduced workflow @@ -1193,9 +1189,9 @@ DECLARE_SOA_TABLE(HfMcCheckLcPis, "AOD", "HFMCCHECKLCPI", //! Table with reconst // Table with same size as HFCANDLc DECLARE_SOA_TABLE(HfMcRecRedLbs, "AOD", "HFMCRECREDLB", //! Reconstruction-level MC information on Lb candidates for reduced workflow - hf_cand_mc_flag::FlagMcMatchRec, - hf_cand_mc_flag::FlagWrongCollision, - hf_cand_mc_flag::DebugMcRec, + hf_cand_lb::FlagMcMatchRec, + hf_cand_lb::FlagWrongCollision, + hf_cand_lb::DebugMcRec, hf_lb_mc::PtMother); DECLARE_SOA_TABLE(HfMcCheckLbs, "AOD", "HFMCCHECKLB", //! Table with reconstructed MC information on Lb candidates for MC checks in reduced workflow @@ -1208,7 +1204,7 @@ DECLARE_SOA_TABLE(HfMcCheckLbs, "AOD", "HFMCCHECKLB", //! Table with reconstruct o2::soa::Marker<2>); DECLARE_SOA_TABLE(HfMcGenRedLbs, "AOD", "HFMCGENREDLB", //! Generation-level MC information on Lb candidates for reduced workflow - hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_lb::FlagMcMatchGen, hf_lb_mc::PtTrack, hf_lb_mc::YTrack, hf_lb_mc::EtaTrack, @@ -1558,7 +1554,7 @@ DECLARE_SOA_TABLE(Hf3PrV0McRec, "AOD", "HF3PRV0MCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand_mc_flag::NTracksDecayed, + hf_cand::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(HfDstarV0McRec, "AOD", "HFDSTARV0MCREC", @@ -1571,7 +1567,7 @@ DECLARE_SOA_TABLE(HfDstarV0McRec, "AOD", "HFDSTARV0MCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand_mc_flag::NTracksDecayed, + hf_cand::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(Hf2PrV0McRec, "AOD", "HF2PRV0MCREC", @@ -1584,7 +1580,7 @@ DECLARE_SOA_TABLE(Hf2PrV0McRec, "AOD", "HF2PRV0MCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand_mc_flag::NTracksDecayed, + hf_cand::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(Hf3PrTrkMcRec, "AOD", "HF3PRTRKMCREC", @@ -1597,7 +1593,7 @@ DECLARE_SOA_TABLE(Hf3PrTrkMcRec, "AOD", "HF3PRTRKMCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand_mc_flag::NTracksDecayed, + hf_cand::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(HfDstarTrkMcRec, "AOD", "HFDSTARTRKMCREC", @@ -1610,7 +1606,7 @@ DECLARE_SOA_TABLE(HfDstarTrkMcRec, "AOD", "HFDSTARTRKMCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand_mc_flag::NTracksDecayed, + hf_cand::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(Hf2PrTrkMcRec, "AOD", "HF2PRTRKMCREC", @@ -1623,11 +1619,11 @@ DECLARE_SOA_TABLE(Hf2PrTrkMcRec, "AOD", "HF2PRTRKMCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand_mc_flag::NTracksDecayed, + hf_cand::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(HfMcGenRedResos, "AOD", "HFMCGENREDRESO", //! Generation-level MC information on Ds-Resonances candidates for reduced workflow - hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_b0::FlagMcMatchGen, hf_reso_cand_reduced::Origin, hf_b0_mc::PtTrack, hf_b0_mc::YTrack, @@ -1651,8 +1647,19 @@ DECLARE_SOA_TABLE(HfMcRecRedResos, "AOD", "HFMCRECREDRESO", //! Reconstruction-l hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand_mc_flag::NTracksDecayed, + hf_cand::NTracksDecayed, o2::soa::Marker<1>); +DECLARE_SOA_TABLE(HcSelTracks, "AOD", "HCSELTRACKS", //! Table with selected tracks for Hc analysis + o2::soa::Index<>, + // Indices + hf_track_index_reduced::TrackId, + hf_track_index_reduced::HfRedCollisionId, + // Static + hf_track_vars_reduced::Px, + hf_track_vars_reduced::Py, + hf_track_vars_reduced::Pz, + hf_track_vars_reduced::Sign, + hf_track_vars_reduced::TrackType); } // namespace aod namespace soa diff --git a/PWGHF/D2H/TableProducer/CMakeLists.txt b/PWGHF/D2H/TableProducer/CMakeLists.txt index 7ad2570bec7..674bbeeb25c 100644 --- a/PWGHF/D2H/TableProducer/CMakeLists.txt +++ b/PWGHF/D2H/TableProducer/CMakeLists.txt @@ -90,6 +90,11 @@ o2physics_add_dpl_workflow(data-creator-jpsi-had-reduced PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(data-creator-hidden-charm-reduced + SOURCES dataCreatorHiddenCharmReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) + # Converters o2physics_add_dpl_workflow(converter-reduced-3-prongs-ml diff --git a/PWGHF/D2H/TableProducer/dataCreatorHiddenCharmReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorHiddenCharmReduced.cxx new file mode 100644 index 00000000000..2c67a04d2a4 --- /dev/null +++ b/PWGHF/D2H/TableProducer/dataCreatorHiddenCharmReduced.cxx @@ -0,0 +1,317 @@ +// 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 dataCreatorHiddenCharmReduced.cxx +/// \brief Reduced data creator for hidden-charm analyses at midrapidity +/// +/// \author A. Palasciano, , INFN Bari +/// \author S. PolitanĂ² , CERN + +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "PWGHF/DataModel/AliasTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/DataModel/TrackIndexSkimmingTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGHF/Utils/utilsEvSelHf.h" + +#include "Common/Core/TPCVDriftManager.h" +#include "Common/Core/ZorroSummary.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::analysis; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::hf_centrality; + +enum TrackType : uint8_t { + Pion = 0, + Kaon, + Proton +}; + +struct HfDataCreatorEtaCToProtonReduced { + + Produces hfReducedCollision; + Produces hfCollisionCounter; + Produces hfTrackLite; + + struct : ConfigurableGroup { + // track quality + Configurable fillHistograms{"fillHistograms", true, "Fill proton QA histograms"}; + Configurable selectProtons{"selectProtons", true, "Select protons"}; + Configurable itsNClsMin{"itsNClsMin", 5, "Minimum number of ITS clusters"}; + Configurable tpcNClsFoundMin{"tpcNClsFoundMin", 50, "Minimum number of found TPC clusters"}; + Configurable tpcNClsCrossedRowsMin{"tpcNClsCrossedRowsMin", 80, "Minimum number of crossed TPC rows"}; + Configurable ptMinTrack{"ptMinTrack", 0.5, "Minimum proton-track pT"}; + Configurable etaMaxTrack{"etaMaxTrack", 0.8, "Maximum proton-track |eta|"}; + Configurable momForCombinedPid{"momForCombinedPid", 0.75f, "Momentum threshold above which combined TPC+TOF proton PID is used"}; + Configurable> binsPtTrack{"binsPtTrack", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "Track pT bin limits for DCA cuts"}; + Configurable> cutsTrack{"cutsTrack", {hf_cuts_single_track::CutsTrack[0], hf_cuts_single_track::NBinsPtTrack, hf_cuts_single_track::NCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, "Single-track DCA selections per pT bin"}; + Configurable maxNsigmaTofPi{"maxNsigmaTofPi", 2.f, "Maximum pion n-sigma in TOF for proton rejection"}; + Configurable maxNsigmaTofKa{"maxNsigmaTofKa", 2.f, "Maximum kaon n-sigma in TOF for proton rejection"}; + Configurable maxNsigmaCombinedPr{"maxNsigmaCombinedPr", 3.f, "Maximum combined proton n-sigma from TPC and TOF"}; + Configurable maxNsigmaTpcPi{"maxNsigmaTpcPi", 2.f, "Maximum pion n-sigma in TPC for proton rejection"}; + Configurable maxNsigmaTpcKa{"maxNsigmaTpcKa", 2.f, "Maximum kaon n-sigma in TPC for proton rejection"}; + Configurable maxNsigmaTpcPr{"maxNsigmaTpcPr", 3.f, "Maximum proton n-sigma in TPC"}; + Configurable forceTOF{"forceTOF", false, "Require TOF PID information for proton selection"}; + } config; + + // other configurables + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; + Configurable doMcRecQa{"doMcRecQa", true, "Fill QA histograms for Mc matching"}; + Configurable rejectPairsWithCommonDaughter{"rejectPairsWithCommonDaughter", true, "flag to reject already at this stage the pairs that share a daughter track"}; + Configurable rejectCollisionsWithBadEvSel{"rejectCollisionsWithBadEvSel", true, "flag to reject collisions with bad event selection"}; + + o2::hf_evsel::HfEventSelection hfEvSel; + o2::hf_evsel::HfEventSelectionMc hfEvSelMc; + + // CCDB service + o2::ccdb::CcdbApi ccdbApi; + Service ccdb{}; + double bz{0.}; + int runNumber{0}; // needed to detect if the run changed and trigger update of calibrations etc. + + // material correction for track propagation + o2::base::MatLayerCylSet* lut{}; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + o2::aod::common::TPCVDriftManager vDriftMgr; + + using BCsInfo = soa::Join; + using TracksWithPID = soa::Join; + Preslice trackIndicesPerCollision = aod::track_association::collisionId; + + HistogramRegistry registry{"registry"}; + OutputObj zorroSummary{"zorroSummary"}; + + void init(InitContext& initContext) + { + // Configure CCDB access + ccdb->setURL(ccdbUrl.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + ccdbApi.init(ccdbUrl); + runNumber = 0; + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); + + if (config.fillHistograms) { + const AxisSpec axisPt{360, 0., 36., "#it{p}_{T}^{proton} (GeV/#it{c})"}; + const AxisSpec axisEta{100, -1., 1., "#eta"}; + const AxisSpec axisDca{400, -2., 2., "DCA_{xy} to primary vertex (cm)"}; + const AxisSpec axisNSigma{100, -5., 5., "n#sigma"}; + + registry.add("hPzVtx", "Z position of primary vertex for selected tracks;z_{vtx} (cm);entries", {HistType::kTH1D, {AxisSpec{200, -20., 20., "z_{vtx} (cm)"}}}); + registry.add("hPtNoCuts", "All associated tracks;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {axisPt}}); + registry.add("hPtCutsProton", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {axisPt}}); + registry.add("hEtaCutsProton", "Selected proton tracks;#eta;entries", {HistType::kTH1D, {axisEta}}); + registry.add("hDCAToPrimXYVsPtCutsProton", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});DCA_{xy} to primary vertex (cm)", {HistType::kTH2D, {axisPt, axisDca}}); + registry.add("hNSigmaTPCProton", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});n#sigma_{TPC}", {HistType::kTH2D, {axisPt, axisNSigma}}); + registry.add("hNSigmaTOFProton", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});n#sigma_{TOF}", {HistType::kTH2D, {axisPt, axisNSigma}}); + registry.add("hInvMass", "Invariant mass of selected proton with all other tracks in the event;#it{p}_{T}^{proton} (GeV/#it{c});invariant mass with other tracks (GeV/#it{c}^{2})", {HistType::kTH2D, {axisPt, AxisSpec{100, 2.85, 3.25, "invariant mass with other tracks (GeV/#it{c}^{2})"}}}); + } + + // init HF event selection helper + hfEvSel.init(registry, &zorroSummary); + + const auto& workflows = initContext.services().get(); + for (const DeviceSpec& device : workflows.devices) { + if (device.name == "hf-data-creator-charm-reso-to-d0-reduced") { + // init HF event selection helper + hfEvSelMc.init(device, registry); + break; + } + } + } + + template + bool isSelectedPid(TTrack const& track) const + { + const float momForCombinedPid = config.momForCombinedPid.value; + const float maxNsigmaTpcPr = config.maxNsigmaTpcPr.value; + const float maxNsigmaTpcPi = config.maxNsigmaTpcPi.value; + const float maxNsigmaTpcKa = config.maxNsigmaTpcKa.value; + const float maxNsigmaCombinedPr = config.maxNsigmaCombinedPr.value; + const float maxNsigmaTofPi = config.maxNsigmaTofPi.value; + const float maxNsigmaTofKa = config.maxNsigmaTofKa.value; + const bool forceTOF = config.forceTOF.value; + + const float mom = std::hypot(track.px(), track.py(), track.pz()); + const float nSigmaTPCPr = track.tpcNSigmaPr(); + const float nSigmaTPCPi = track.tpcNSigmaPi(); + const float nSigmaTPCKa = track.tpcNSigmaKa(); + const bool hasTOF = track.hasTOF(); + if (!hasTOF && forceTOF) { + return false; + } + + bool isProton = false; + bool rejectAsPion = false; + bool rejectAsKaon = false; + + if (mom < momForCombinedPid || !hasTOF) { + isProton = std::abs(nSigmaTPCPr) < maxNsigmaTpcPr; + rejectAsPion = std::abs(nSigmaTPCPi) < maxNsigmaTpcPi; + rejectAsKaon = std::abs(nSigmaTPCKa) < maxNsigmaTpcKa; + } else { + const float nSigmaTOFPr = track.tofNSigmaPr(); + const float nSigmaTOFPi = track.tofNSigmaPi(); + const float nSigmaTOFKa = track.tofNSigmaKa(); + isProton = std::hypot(nSigmaTPCPr, nSigmaTOFPr) < maxNsigmaCombinedPr; + rejectAsPion = std::hypot(nSigmaTPCPi, nSigmaTOFPi) < maxNsigmaTofPi; + rejectAsKaon = std::hypot(nSigmaTPCKa, nSigmaTOFKa) < maxNsigmaTofKa; + } + return isProton && !rejectAsPion && !rejectAsKaon; + } + + template + bool isSelectedTrack(TTrack const& track) const + { + const int tpcNClsFoundMin = config.tpcNClsFoundMin.value; + const int tpcNClsCrossedRowsMin = config.tpcNClsCrossedRowsMin.value; + const int itsNClsMin = config.itsNClsMin.value; + const double etaMaxTrack = config.etaMaxTrack.value; + const double ptMinTrack = config.ptMinTrack.value; + + if (!track.isGlobalTrackWoDCA()) { + return false; + } + if (track.tpcNClsFound() < tpcNClsFoundMin) { + return false; + } + if (track.tpcNClsCrossedRows() < tpcNClsCrossedRowsMin) { + return false; + } + if (track.itsNCls() < itsNClsMin) { + return false; + } + if (std::abs(track.eta()) > etaMaxTrack) { + return false; + } + if (track.pt() < ptMinTrack) { + return false; + } + if (!isSelectedTrackDca(config.binsPtTrack, config.cutsTrack, track.pt(), track.dcaXY(), track.dcaZ())) { + return false; + } + return isSelectedPid(track); + } + + void processEtaCTrack(soa::Join const& collisions, + aod::TrackAssoc const& trackIndices, + TracksWithPID const& tracks, + aod::BCsWithTimestamps const&) + { + hfTrackLite.reserve(tracks.size()); + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + const auto hfRejMap = o2::hf_evsel::getEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + if (rejectCollisionsWithBadEvSel && hfRejMap != 0) { + continue; + } + const auto thisCollId = collision.globalIndex(); + const auto trackIds = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + if (config.fillHistograms) { + registry.fill(HIST("hPzVtx"), collision.posZ()); + } + std::vector selectedTrackIds; + for (const auto& trkId : trackIds) { + auto trk = trkId.track_as(); + if (config.fillHistograms) { + registry.fill(HIST("hPtNoCuts"), trk.pt()); + } + if (!isSelectedTrack(trk)) { + continue; + } + std::array pVecProton{trk.pVector()}; + hfTrackLite(trk.globalIndex(), collision.globalIndex(), pVecProton[0], pVecProton[1], pVecProton[2], trk.sign(), static_cast(TrackType::Proton)); + selectedTrackIds.push_back(trk.globalIndex()); + if (config.fillHistograms) { + registry.fill(HIST("hPtCutsProton"), trk.pt()); + registry.fill(HIST("hEtaCutsProton"), trk.eta()); + registry.fill(HIST("hDCAToPrimXYVsPtCutsProton"), trk.pt(), trk.dcaXY()); + registry.fill(HIST("hNSigmaTPCProton"), trk.pt(), trk.tpcNSigmaPr()); + if (trk.hasTOF()) { + registry.fill(HIST("hNSigmaTOFProton"), trk.pt(), trk.tofNSigmaPr()); + } + } + } + if (selectedTrackIds.size() < 2) { + continue; + } + hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), hfRejMap, bz); + for (size_t i = 0; i < selectedTrackIds.size(); ++i) { + auto t1 = tracks.rawIteratorAt(selectedTrackIds[i]); + std::array pVec1{t1.pVector()}; + for (size_t j = i + 1; j < selectedTrackIds.size(); ++j) { + auto t2 = tracks.rawIteratorAt(selectedTrackIds[j]); + if (t1.sign() * t2.sign() > 0) { + continue; + } + std::array pVec2{t2.pVector()}; + float invMass = RecoDecay::m(std::array{pVec1, pVec2}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassProton}); + float ptEtac = RecoDecay::pt(RecoDecay::sumOfVec(pVec1, pVec2)); + if (config.fillHistograms) { + registry.fill(HIST("hInvMass"), ptEtac, invMass); + } + } + } + } + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + + PROCESS_SWITCH(HfDataCreatorEtaCToProtonReduced, processEtaCTrack, "EtaC -> p pbar reconstruction", true); +}; + +// struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{}; + workflow.push_back(adaptAnalysisTask(cfgc)); + return workflow; +} diff --git a/PWGHF/D2H/Tasks/CMakeLists.txt b/PWGHF/D2H/Tasks/CMakeLists.txt index 40f2358fdaf..608145a8e51 100644 --- a/PWGHF/D2H/Tasks/CMakeLists.txt +++ b/PWGHF/D2H/Tasks/CMakeLists.txt @@ -153,3 +153,8 @@ o2physics_add_dpl_workflow(task-xic0-to-xi-pi SOURCES taskXic0ToXiPi.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(task-hidden-charm + SOURCES taskHiddenCharm.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGHF/D2H/Tasks/taskHiddenCharm.cxx b/PWGHF/D2H/Tasks/taskHiddenCharm.cxx new file mode 100644 index 00000000000..8ff4d7a8ea2 --- /dev/null +++ b/PWGHF/D2H/Tasks/taskHiddenCharm.cxx @@ -0,0 +1,146 @@ +// 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 taskHiddenCharm.cxx +/// \brief Analysis task for hidden charm hadrons at midrapidity +/// +/// \author A. Palasciano, , INFN Bari +/// \author S. PolitanĂ² , CERN + +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::hf_centrality; + +enum TrackType : uint8_t { + Pion = 0, + Kaon, + Proton +}; + +struct HfHiddenCharmHadrons { + Configurable centEstimator{"centEstimator", 0, "Centrality estimation (None: 0, FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4, NTracksPV: 5, FT0CVariant2: 6)"}; + Configurable centralityMin{"centralityMin", 0.f, "Minimum accepted centrality"}; + Configurable centralityMax{"centralityMax", 100.f, "Maximum accepted centrality"}; + Configurable fillOnlyUnlikeSign{"fillOnlyUnlikeSign", true, "Fill only unlike-sign proton pairs"}; + Configurable fillOnlyLikeSign{"fillOnlyLikeSign", true, "Fill only like-sign proton pairs"}; + + ConfigurableAxis thnConfigAxisInvMass{"thnConfigAxisInvMass", {1400, 2.8, 4.2}, ""}; + ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {100, 0., 10.}, ""}; + ConfigurableAxis thnConfigAxisCent{"thnConfigAxisCent", {100, 0., 100.}, ""}; + ConfigurableAxis thnConfigAxisSign{"thnConfigAxisSign", {2, -1., 1.}, ""}; + + SliceCache cache; + + using SelectedCollisionsPP = aod::HfRedCollisions; + using SelectedCollisionsPbPb = soa::Join; + + Partition selectedProtons = aod::hf_track_vars_reduced::tracktype == static_cast(TrackType::Proton); + Partition selectedPions = aod::hf_track_vars_reduced::tracktype == static_cast(TrackType::Pion); + Partition selectedKaons = aod::hf_track_vars_reduced::tracktype == static_cast(TrackType::Kaon); + + HistogramRegistry registry{"registry", {}}; + + void init(InitContext&) + { + const AxisSpec axisInvMass{thnConfigAxisInvMass, "M_{p#bar{p}} (GeV/#it{c}^{2})"}; + const AxisSpec axisPt{thnConfigAxisPt, "#it{p}_{T}^{p#bar{p}} (GeV/#it{c})"}; + const AxisSpec axisCent{thnConfigAxisCent, "Centrality"}; + const AxisSpec axisSign{thnConfigAxisSign, "q_{1} #times q_{2}"}; + + registry.add("hSparseHiddenCharm", "Hidden-charm proton-pair candidates", HistType::kTHnSparseF, {axisInvMass, axisPt, axisSign, axisCent}); + registry.add("hPtVsInvMassLikeSign", "Hidden-charm LS M_{inv}", HistType::kTH2D, {axisInvMass, axisPt}); + registry.add("hPtVsInvMassUnlikeSign", "Hidden-charm proton-pair ULS", HistType::kTH2D, {axisInvMass, axisPt}); + registry.add("hPtVsInvMassAllSign", "Hidden-charm proton-pair LS+ULS M_{inv}", HistType::kTH2D, {axisInvMass, axisPt}); + } + + template + void fillEtac(TCollisions const& collision, + TProtonIds const& protonIds) + { + float cent{-1.f}; + if constexpr (CentEstimator != o2::hf_centrality::CentralityEstimator::None) { + cent = o2::hf_centrality::getCentralityColl(collision, centEstimator); + if (cent < centralityMin || cent >= centralityMax) { + return; // skip events outside the centrality range + } + } + + for (const auto& proton1 : protonIds) { + for (const auto& proton2 : protonIds) { + if (proton1.trackId() >= proton2.trackId()) { + continue; // avoid double counting and self-pairs + } + const int sign = (proton1.sign() * proton2.sign() > 0) ? 1 : -1; + if ((sign == 1 && !fillOnlyLikeSign) || (sign == -1 && !fillOnlyUnlikeSign)) { + continue; + } + std::array pVec1{proton1.px(), proton1.py(), proton1.pz()}; + std::array pVec2{proton2.px(), proton2.py(), proton2.pz()}; + float invMass = RecoDecay::m(std::array{pVec1, pVec2}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassProton}); + float ptEtac = RecoDecay::pt(RecoDecay::sumOfVec(pVec1, pVec2)); + registry.fill(HIST("hSparseHiddenCharm"), invMass, ptEtac, sign, cent); + if (sign == 1) { + registry.fill(HIST("hPtVsInvMassLikeSign"), invMass, ptEtac); + } else if (sign == -1) { + registry.fill(HIST("hPtVsInvMassUnlikeSign"), invMass, ptEtac); + registry.fill(HIST("hPtVsInvMassAllSign"), invMass, ptEtac); + } + } + } + } + + void processEtacPP(SelectedCollisionsPP::iterator const& collision, + aod::HcSelTracks const& /*tracks*/) + { + auto candProtons = selectedProtons->sliceByCached(aod::hf_track_index_reduced::hfRedCollisionId, collision.globalIndex(), cache); + fillEtac(collision, candProtons); + } + PROCESS_SWITCH(HfHiddenCharmHadrons, processEtacPP, "Process Etac candidates for pp", true); + + // void processEtacPbPb(SelectedCollisionsPbPb::iterator const& collisions, + // aod::HcSelTracks const& protonIds) + //{ + // fillEtac(collisions, protonIds, true); + // } + // PROCESS_SWITCH(HfHiddenCharmHadrons, processEtacPbPb, "Process Etac candidates for PbPb", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +}