From 6243c30e9827d22a6d32e4b351eab1873c1659a9 Mon Sep 17 00:00:00 2001 From: Valerio Di Bella Date: Wed, 3 Dec 2025 11:16:57 +0100 Subject: [PATCH] Introducing a reduced workflow for D+ pairs --- .../HFC/DataModel/ReducedDMesonPairsTables.h | 234 ++++++++++++ PWGHF/HFC/TableProducer/CMakeLists.txt | 5 + .../correlatorDplusDplusReduced.cxx | 354 ++++++++++++++++++ PWGHF/HFC/Tasks/CMakeLists.txt | 5 + .../taskCorrelationDplusDplusReduced.cxx | 100 +++++ 5 files changed, 698 insertions(+) create mode 100644 PWGHF/HFC/DataModel/ReducedDMesonPairsTables.h create mode 100644 PWGHF/HFC/TableProducer/correlatorDplusDplusReduced.cxx create mode 100644 PWGHF/HFC/Tasks/taskCorrelationDplusDplusReduced.cxx diff --git a/PWGHF/HFC/DataModel/ReducedDMesonPairsTables.h b/PWGHF/HFC/DataModel/ReducedDMesonPairsTables.h new file mode 100644 index 00000000000..10fb388e224 --- /dev/null +++ b/PWGHF/HFC/DataModel/ReducedDMesonPairsTables.h @@ -0,0 +1,234 @@ +// 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 ReducedDMesonPairsTables.h +/// \brief Header file with definition of methods and tables +/// \note used to fold (unfold) track and primary vertex information by writing (reading) AO2Ds +/// +/// \author Valerio DI BELLA , IPHC Strasbourg + +#ifndef PWGHF_HFC_DATAMODEL_REDUCEDDMESONPAIRSTABLES_H_ +#define PWGHF_HFC_DATAMODEL_REDUCEDDMESONPAIRSTABLES_H_ + +#include "PWGHF/DataModel/CandidateReconstructionTables.h" + +namespace o2::aod +{ +DECLARE_SOA_TABLE(HfCandDpFullEvs, "AOD", "HFCANDDPFULLEV", + collision::NumContrib, + collision::PosX, + collision::PosY, + collision::PosZ); + +DECLARE_SOA_TABLE(HfCandDpMcEvs, "AOD", "HFCANDDPMCEV", + collision::PosX, + collision::PosY, + collision::PosZ); + +namespace full +{ +DECLARE_SOA_COLUMN(RSecondaryVertex, rSecondaryVertex, float); //! Radius of secondary vertex (cm) +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of prong0 (GeV/c) +DECLARE_SOA_COLUMN(PProng0, pProng0, float); //! Momentum of prong0 (GeV/c) +DECLARE_SOA_COLUMN(ImpactParameterNormalised0, impactParameterNormalised0, float); //! Normalised impact parameter of prong0 +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of prong1 (GeV/c) +DECLARE_SOA_COLUMN(PProng1, pProng1, float); //! Momentum of prong1 (in GeV/c) +DECLARE_SOA_COLUMN(ImpactParameterNormalised1, impactParameterNormalised1, float); //! Normalised impact parameter of prong1 +DECLARE_SOA_COLUMN(PtProng2, ptProng2, float); //! Transverse momentum of prong2 (GeV/c) +DECLARE_SOA_COLUMN(PProng2, pProng2, float); //! Momentum of prong2 (GeV/c) +DECLARE_SOA_COLUMN(ImpactParameterNormalised2, impactParameterNormalised2, float); //! Normalised impact parameter of prong2 +DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int); //! Selection flag of candidate (output of candidateSelector) +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(Y, y, float); //! Rapidity of candidate +DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate +DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate +DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) +DECLARE_SOA_COLUMN(Centrality, centrality, float); //! Collision centrality +DECLARE_SOA_INDEX_COLUMN(HfCandDpMcEv, hfCandDpMcEv); //! The Mc collision index this MC particles belongs to +DECLARE_SOA_INDEX_COLUMN(HfCandDpFullEv, hfCandDpFullEv); //! The collision index this candidate belongs to +DECLARE_SOA_COLUMN(NSigTpcPi0, nSigTpcPi0, float); //! TPC Nsigma separation for prong0 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcKa0, nSigTpcKa0, float); //! TPC Nsigma separation for prong0 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi0, nSigTofPi0, float); //! TOF Nsigma separation for prong0 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofKa0, nSigTofKa0, float); //! TOF Nsigma separation for prong0 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); //! TPC Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcKa1, nSigTpcKa1, float); //! TPC Nsigma separation for prong1 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofKa1, nSigTofKa1, float); //! TOF Nsigma separation for prong1 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcPi2, nSigTpcPi2, float); //! TPC Nsigma separation for prong2 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcKa2, nSigTpcKa2, float); //! TPC Nsigma separation for prong2 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi2, nSigTofPi2, float); //! TOF Nsigma separation for prong2 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofKa2, nSigTofKa2, float); //! TOF Nsigma separation for prong2 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofPi0, nSigTpcTofPi0, float); //! TPC and TOF combined Nsigma separation for prong0 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofKa0, nSigTpcTofKa0, float); //! TPC and TOF combined Nsigma separation for prong0 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofPi1, nSigTpcTofPi1, float); //! TPC and TOF combined Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofKa1, nSigTpcTofKa1, float); //! TPC and TOF combined Nsigma separation for prong1 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofPi2, nSigTpcTofPi2, float); //! TPC and TOF combined Nsigma separation for prong2 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofKa2, nSigTpcTofKa2, float); //! TPC and TOF combined Nsigma separation for prong2 with kaon mass hypothesis +DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Transverse decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! Normalised decay length of candidate +DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! Normalised transverse decay length of candidate +DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine pointing angle of candidate +DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine pointing angle of candidate in transverse plane +DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs +DECLARE_SOA_COLUMN(Ct, ct, float); //! Proper lifetime times c of candidate (cm) +// Events +DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); //! Event rejection flag +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); //! Run number +// ML scores +DECLARE_SOA_COLUMN(MlScore0, mlScore0, float); //! ML score of the first configured index +DECLARE_SOA_COLUMN(MlScore1, mlScore1, float); //! ML score of the second configured index +} // namespace full +DECLARE_SOA_TABLE(HfCandDpMls, "AOD", "HFCANDDPML", + full::MlScore0, + full::MlScore1) + +DECLARE_SOA_TABLE(HfCandDpLites, "AOD", "HFCANDDPLITE", + hf_cand::Chi2PCA, + full::DecayLength, + full::DecayLengthXY, + full::DecayLengthNormalised, + full::DecayLengthXYNormalised, + full::PtProng0, + full::PtProng1, + full::PtProng2, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + hf_cand::ImpactParameter2, + hf_cand::ImpactParameterZ0, + hf_cand::ImpactParameterZ1, + hf_cand::ImpactParameterZ2, + full::NSigTpcPi0, + full::NSigTpcKa0, + full::NSigTofPi0, + full::NSigTofKa0, + full::NSigTpcTofPi0, + full::NSigTpcTofKa0, + full::NSigTpcPi1, + full::NSigTpcKa1, + full::NSigTofPi1, + full::NSigTofKa1, + full::NSigTpcTofPi1, + full::NSigTpcTofKa1, + full::NSigTpcPi2, + full::NSigTpcKa2, + full::NSigTofPi2, + full::NSigTofKa2, + full::NSigTpcTofPi2, + full::NSigTpcTofKa2, + full::CandidateSelFlag, + full::M, + full::Pt, + full::Cpa, + full::CpaXY, + full::MaxNormalisedDeltaIP, + full::Eta, + full::Phi, + full::Y, + full::Centrality, + collision::NumContrib, + full::HfCandDpFullEvId, + hf_cand_3prong::FlagMcMatchRec, + hf_cand_3prong::OriginMcRec, + hf_cand_3prong::FlagMcDecayChanRec) + +DECLARE_SOA_TABLE(HfCandDpFulls, "AOD", "HFCANDDPFULL", + hf_cand::XSecondaryVertex, + hf_cand::YSecondaryVertex, + hf_cand::ZSecondaryVertex, + hf_cand::ErrorDecayLength, + hf_cand::ErrorDecayLengthXY, + hf_cand::Chi2PCA, + full::RSecondaryVertex, + full::DecayLength, + full::DecayLengthXY, + full::DecayLengthNormalised, + full::DecayLengthXYNormalised, + full::ImpactParameterNormalised0, + full::PtProng0, + full::PProng0, + full::ImpactParameterNormalised1, + full::PtProng1, + full::PProng1, + full::ImpactParameterNormalised2, + full::PtProng2, + full::PProng2, + hf_cand::PxProng0, + hf_cand::PyProng0, + hf_cand::PzProng0, + hf_cand::PxProng1, + hf_cand::PyProng1, + hf_cand::PzProng1, + hf_cand::PxProng2, + hf_cand::PyProng2, + hf_cand::PzProng2, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + hf_cand::ImpactParameter2, + hf_cand::ErrorImpactParameter0, + hf_cand::ErrorImpactParameter1, + hf_cand::ErrorImpactParameter2, + hf_cand::ImpactParameterZ0, + hf_cand::ImpactParameterZ1, + hf_cand::ImpactParameterZ2, + hf_cand::ErrorImpactParameterZ0, + hf_cand::ErrorImpactParameterZ1, + hf_cand::ErrorImpactParameterZ2, + full::NSigTpcPi0, + full::NSigTpcKa0, + full::NSigTofPi0, + full::NSigTofKa0, + full::NSigTpcTofPi0, + full::NSigTpcTofKa0, + full::NSigTpcPi1, + full::NSigTpcKa1, + full::NSigTofPi1, + full::NSigTofKa1, + full::NSigTpcTofPi1, + full::NSigTpcTofKa1, + full::NSigTpcPi2, + full::NSigTpcKa2, + full::NSigTofPi2, + full::NSigTofKa2, + full::NSigTpcTofPi2, + full::NSigTpcTofKa2, + full::CandidateSelFlag, + full::M, + full::Pt, + full::P, + full::Cpa, + full::CpaXY, + full::MaxNormalisedDeltaIP, + full::Ct, + full::Eta, + full::Phi, + full::Y, + full::E, + full::Centrality, + full::HfCandDpFullEvId, + hf_cand_3prong::FlagMcMatchRec, + hf_cand_3prong::OriginMcRec, + hf_cand_3prong::FlagMcDecayChanRec); + +DECLARE_SOA_TABLE(HfCandDpMcPs, "AOD", "HFCANDDPMCP", + full::Pt, + full::Eta, + full::Phi, + full::Y, + full::HfCandDpMcEvId, + hf_cand_3prong::FlagMcMatchGen, + hf_cand_3prong::FlagMcDecayChanGen, + hf_cand_3prong::OriginMcGen); +} // namespace o2::aod + +#endif // PWGHF_HFC_DATAMODEL_REDUCEDDMESONPAIRSTABLES_H_ diff --git a/PWGHF/HFC/TableProducer/CMakeLists.txt b/PWGHF/HFC/TableProducer/CMakeLists.txt index fbf7a06c6dc..eb49d38720b 100644 --- a/PWGHF/HFC/TableProducer/CMakeLists.txt +++ b/PWGHF/HFC/TableProducer/CMakeLists.txt @@ -34,6 +34,11 @@ o2physics_add_dpl_workflow(correlator-dplus-dminus PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(correlator-dplus-dplus-reduced + SOURCES correlatorDplusDplusReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(correlator-dplus-hadrons SOURCES correlatorDplusHadrons.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGHF/HFC/TableProducer/correlatorDplusDplusReduced.cxx b/PWGHF/HFC/TableProducer/correlatorDplusDplusReduced.cxx new file mode 100644 index 00000000000..966d7293a8a --- /dev/null +++ b/PWGHF/HFC/TableProducer/correlatorDplusDplusReduced.cxx @@ -0,0 +1,354 @@ +// 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 correlatorDplusDplusReduced.cxx +/// \brief Writer of D+ → π+ K- π+ candidates in the form of flat tables to be stored in TTrees. +/// Intended for debug, local optimization of analysis on small samples or ML training. +/// In this file are defined and filled the output tables +/// +/// \author Valerio DI BELLA , IPHC Strasbourg +/// Based on the code of Alexandre Bigot , IPHC Strasbourg + +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/HFC/DataModel/ReducedDMesonPairsTables.h" + +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::hf_centrality; + +/// Writes the full information in an output TTree +struct HfCorrelatorDplusDplusReduced { + Produces rowCandidateFull; + Produces rowCandidateLite; + Produces rowCandidateFullEvents; + Produces rowCandidateMl; + + Produces rowCandidateMcParticles; + Produces rowCandidateMcCollisions; + + Configurable selectionFlagDplus{"selectionFlagDplus", 1, "Selection Flag for Dplus"}; + Configurable fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"}; + // parameters for production of training samples + Configurable fillCorrBkgs{"fillCorrBkgs", false, "Flag to fill derived tables with correlated background candidates"}; + Configurable> classMlIndexes{"classMlIndexes", {0, 2}, "Indexes of ML bkg and non-prompt scores."}; + Configurable centEstimator{"centEstimator", 0, "Centrality estimation (None: 0, FT0C: 2, FT0M: 3)"}; + Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", true, "Enables processing of skimmed datasets"}; + Configurable skipSingleD{"skipSingleD", true, "Skip collisions with one or less D candidates"}; + + HfHelper hfHelper; + + Service ccdb; + + using SelectedCandidates = soa::Filtered>; + using SelectedCandidatesMc = soa::Filtered>; + using MatchedGenCandidatesMc = soa::Filtered>; + using SelectedCandidatesMcWithMl = soa::Filtered>; + using CollisionsCent = soa::Join; + + Filter filterSelectCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Filter filterMcGenMatching = (nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) != 0)); + + Preslice tracksPerCollision = o2::aod::track::collisionId; + Preslice mcParticlesPerMcCollision = o2::aod::mcparticle::mcCollisionId; + + Partition reconstructedCandSig = (nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_3prong::flagMcMatchRec) != 0)); + Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Partition reconstructedCandSigMl = (nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_3prong::flagMcMatchRec) != 0)); + + HistogramRegistry registry{"registry"}; + Zorro zorro; + OutputObj zorroSummary{"zorroSummary"}; + + void init(InitContext const&) + { + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + if (cfgSkimmedProcessing) { + zorroSummary.setObject(zorro.getZorroSummary()); + } + } + + template + void fillEvent(const T& collision) + { + rowCandidateFullEvents( + collision.numContrib(), + collision.posX(), + collision.posY(), + collision.posZ()); + } + + template + void fillCandidateTable(const T& candidate, int localEvIdx = -1) + { + int8_t flagMc = 0; + int8_t originMc = 0; + int8_t channelMc = 0; + if constexpr (doMc) { + flagMc = candidate.flagMcMatchRec(); + originMc = candidate.originMcRec(); + channelMc = candidate.flagMcDecayChanRec(); + } + + std::vector outputMl = {-999., -999.}; + if constexpr (doMl) { + for (unsigned int iclass = 0; iclass < classMlIndexes->size(); iclass++) { + outputMl[iclass] = candidate.mlProbDplusToPiKPi()[classMlIndexes->at(iclass)]; + } + rowCandidateMl( + outputMl[0], + outputMl[1]); + } + + float cent{-1.}; + auto coll = candidate.template collision_as(); + if (std::is_same_v && centEstimator != CentralityEstimator::None) { + cent = getCentralityColl(coll, centEstimator); + } + + if (fillCandidateLiteTable) { + rowCandidateLite( + candidate.chi2PCA(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.ptProng0(), + candidate.ptProng1(), + candidate.ptProng2(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameter2(), + candidate.impactParameterZ0(), + candidate.impactParameterZ1(), + candidate.impactParameterZ2(), + candidate.nSigTpcPi0(), + candidate.nSigTpcKa0(), + candidate.nSigTofPi0(), + candidate.nSigTofKa0(), + candidate.tpcTofNSigmaPi0(), + candidate.tpcTofNSigmaKa0(), + candidate.nSigTpcPi1(), + candidate.nSigTpcKa1(), + candidate.nSigTofPi1(), + candidate.nSigTofKa1(), + candidate.tpcTofNSigmaPi1(), + candidate.tpcTofNSigmaKa1(), + candidate.nSigTpcPi2(), + candidate.nSigTpcKa2(), + candidate.nSigTofPi2(), + candidate.nSigTofKa2(), + candidate.tpcTofNSigmaPi2(), + candidate.tpcTofNSigmaKa2(), + candidate.isSelDplusToPiKPi(), + hfHelper.invMassDplusToPiKPi(candidate), + candidate.pt(), + candidate.cpa(), + candidate.cpaXY(), + candidate.maxNormalisedDeltaIP(), + candidate.eta(), + candidate.phi(), + hfHelper.yDplus(candidate), + cent, + coll.numContrib(), + localEvIdx, + flagMc, + originMc, + channelMc); + } else { + rowCandidateFull( + candidate.xSecondaryVertex(), + candidate.ySecondaryVertex(), + candidate.zSecondaryVertex(), + candidate.errorDecayLength(), + candidate.errorDecayLengthXY(), + candidate.chi2PCA(), + candidate.rSecondaryVertex(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.impactParameterNormalised0(), + candidate.ptProng0(), + RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), + candidate.impactParameterNormalised1(), + candidate.ptProng1(), + RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()), + candidate.impactParameterNormalised2(), + candidate.ptProng2(), + RecoDecay::p(candidate.pxProng2(), candidate.pyProng2(), candidate.pzProng2()), + candidate.pxProng0(), + candidate.pyProng0(), + candidate.pzProng0(), + candidate.pxProng1(), + candidate.pyProng1(), + candidate.pzProng1(), + candidate.pxProng2(), + candidate.pyProng2(), + candidate.pzProng2(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameter2(), + candidate.errorImpactParameter0(), + candidate.errorImpactParameter1(), + candidate.errorImpactParameter2(), + candidate.impactParameterZ0(), + candidate.impactParameterZ1(), + candidate.impactParameterZ2(), + candidate.errorImpactParameterZ0(), + candidate.errorImpactParameterZ1(), + candidate.errorImpactParameterZ2(), + candidate.nSigTpcPi0(), + candidate.nSigTpcKa0(), + candidate.nSigTofPi0(), + candidate.nSigTofKa0(), + candidate.tpcTofNSigmaPi0(), + candidate.tpcTofNSigmaKa0(), + candidate.nSigTpcPi1(), + candidate.nSigTpcKa1(), + candidate.nSigTofPi1(), + candidate.nSigTofKa1(), + candidate.tpcTofNSigmaPi1(), + candidate.tpcTofNSigmaKa1(), + candidate.nSigTpcPi2(), + candidate.nSigTpcKa2(), + candidate.nSigTofPi2(), + candidate.nSigTofKa2(), + candidate.tpcTofNSigmaPi2(), + candidate.tpcTofNSigmaKa2(), + candidate.isSelDplusToPiKPi(), + hfHelper.invMassDplusToPiKPi(candidate), + candidate.pt(), + candidate.p(), + candidate.cpa(), + candidate.cpaXY(), + candidate.maxNormalisedDeltaIP(), + hfHelper.ctDplus(candidate), + candidate.eta(), + candidate.phi(), + hfHelper.yDplus(candidate), + hfHelper.eDplus(candidate), + cent, + localEvIdx, + flagMc, + originMc, + channelMc); + } + } + + void processData(aod::Collisions const& collisions, SelectedCandidates const& candidates) + { + static int lastRunNumber = -1; + // reserve memory + rowCandidateFullEvents.reserve(collisions.size()); + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(candidates.size()); + } else { + rowCandidateFull.reserve(candidates.size()); + } + + for (const auto& collision : collisions) { + if (cfgSkimmedProcessing) { + auto bc = collision.bc_as(); + int runNumber = bc.runNumber(); + if (lastRunNumber != runNumber) { + lastRunNumber = runNumber; + LOGF(info, "Initializing Zorro for run %d", runNumber); + uint64_t currentTimestamp = bc.timestamp(); + zorro.initCCDB(ccdb.service, runNumber, currentTimestamp, "fHfDoubleCharm3P"); + zorro.populateHistRegistry(registry, runNumber); + } + zorro.isSelected(bc.globalBC()); + } + + const auto colId = collision.globalIndex(); + auto candidatesInThisCollision = candidates.sliceBy(tracksPerCollision, colId); + if (skipSingleD) + if (candidatesInThisCollision.size() < 2) // o2-linter: disable=magic-number (number of candidate must be larger than 1) + continue; + fillEvent(collision); + for (const auto& candidate : candidatesInThisCollision) { + fillCandidateTable(candidate, rowCandidateFullEvents.lastIndex()); + } + } + } + PROCESS_SWITCH(HfCorrelatorDplusDplusReduced, processData, "Process data per collision", false); + + void processMcRec(aod::Collisions const& collisions, + SelectedCandidatesMc const& candidates) + { + // reserve memory + rowCandidateFullEvents.reserve(collisions.size()); + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(candidates.size()); + } else { + rowCandidateFull.reserve(candidates.size()); + } + + for (const auto& collision : collisions) { // No skimming for MC data. No Zorro ! + const auto colId = collision.globalIndex(); + auto candidatesInThisCollision = candidates.sliceBy(tracksPerCollision, colId); + if (skipSingleD) + if (candidatesInThisCollision.size() < 2) // o2-linter: disable=magic-number (number of candidate must be larger than 1) + continue; + fillEvent(collision); + for (const auto& candidate : candidatesInThisCollision) { + fillCandidateTable(candidate, rowCandidateFullEvents.lastIndex()); + } + } + } + PROCESS_SWITCH(HfCorrelatorDplusDplusReduced, processMcRec, "Process data per collision", false); + + void processMcGen(aod::McCollisions const& mccollisions, MatchedGenCandidatesMc const& mcparticles) + { + // reserve memory + rowCandidateMcCollisions.reserve(mccollisions.size()); + rowCandidateMcParticles.reserve(mcparticles.size()); + + for (const auto& mccollision : mccollisions) { // No skimming for MC data. No Zorro ! + const auto colId = mccollision.globalIndex(); + const auto particlesInThisCollision = mcparticles.sliceBy(mcParticlesPerMcCollision, colId); + if (skipSingleD) + if (particlesInThisCollision.size() < 2) // o2-linter: disable=magic-number (number of candidate must be larger than 1) + continue; + rowCandidateMcCollisions( + mccollision.posX(), + mccollision.posY(), + mccollision.posZ()); + for (const auto& particle : particlesInThisCollision) { + rowCandidateMcParticles( + particle.pt(), + particle.eta(), + particle.phi(), + particle.y(), + rowCandidateMcCollisions.lastIndex(), + particle.flagMcMatchGen(), + particle.flagMcDecayChanGen(), + particle.originMcGen()); + } + } + } + PROCESS_SWITCH(HfCorrelatorDplusDplusReduced, processMcGen, "Process MC data at the generator level", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/HFC/Tasks/CMakeLists.txt b/PWGHF/HFC/Tasks/CMakeLists.txt index 9db29e2030f..4792d35551b 100644 --- a/PWGHF/HFC/Tasks/CMakeLists.txt +++ b/PWGHF/HFC/Tasks/CMakeLists.txt @@ -29,6 +29,11 @@ o2physics_add_dpl_workflow(task-correlation-d-meson-pairs PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-correlation-dplus-dplus-reduced + SOURCES taskCorrelationDplusDplusReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(task-correlation-dplus-hadrons SOURCES taskCorrelationDplusHadrons.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGHF/HFC/Tasks/taskCorrelationDplusDplusReduced.cxx b/PWGHF/HFC/Tasks/taskCorrelationDplusDplusReduced.cxx new file mode 100644 index 00000000000..4d6e64a22dc --- /dev/null +++ b/PWGHF/HFC/Tasks/taskCorrelationDplusDplusReduced.cxx @@ -0,0 +1,100 @@ +// 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 TaskCorrelationDplusDplusReduced.cxx +/// \brief Writer of pairs of D mesons candidates in the form of flat tables to be stored in TTrees. +/// Intended for debug, local optimization of analysis on small samples or ML training. +/// In this file are defined and filled the output tables +/// +/// \author Valerio DI BELLA , IPHC Strasbourg +/// Based on the code of Alexandre Bigot , IPHC Strasbourg + +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/HFC/DataModel/ReducedDMesonPairsTables.h" + +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct HfTaskCorrelationDplusDplusReduced { + Configurable selectionFlagDplus{"selectionFlagDplus", 1, "Selection Flag for Dplus"}; + + using SelectedCandidates = soa::Filtered; + using SelectedMcParticles = o2::aod::HfCandDpMcPs; + + Filter filterSelectCandidates = aod::full::candidateSelFlag >= selectionFlagDplus; + + HistogramConfigSpec hTH1NCand{HistType::kTH1F, {{7, -0.5, 6.5}}}; + HistogramConfigSpec hTH1NMcRec{HistType::kTH1F, {{7, -0.5, 6.5}}}; + HistogramConfigSpec hTH1NMcGen{HistType::kTH1F, {{7, -0.5, 6.5}}}; + HistogramRegistry registry{ + "registry", + {{"hNCand", "Number of D candidates per event;N", hTH1NCand}, + {"hNMcRec", "Number of reconstructed Mc D mesons per event;N", hTH1NMcRec}, + {"hNMcGen", "Number of generated Mc D mesons per event;N", hTH1NMcGen}}}; + void init(InitContext const&) + { + registry.add("hMassDplus", "D+ candidates;inv. mass (#pi#pi K) (GeV/#it{c}^{2}))", {HistType::kTH1F, {{120, 1.5848, 2.1848}}}); + registry.add("hMassDplusMatched", "D+ matched candidates;inv. mass (#pi#pi K) (GeV/#it{c}^{2}))", {HistType::kTH1F, {{120, 1.5848, 2.1848}}}); + registry.add("hMassDMesonPair", "D Meson pair candidates;inv. mass (#pi K) (GeV/#it{c}^{2});inv. mass (#pi K) (GeV/#it{c}^{2})", {HistType::kTH2F, {{120, 1.5848, 2.1848}, {120, 1.5848, 2.1848}}}); + registry.add("hDltPhiMcGen", "Azimuthal correlation for D mesons; #Delta#phi", {HistType::kTH1F, {{100, -3.141593, 3.141593}}}); + } + + void processLocalData(o2::aod::HfCandDpFullEvs::iterator const&, + SelectedCandidates const& localCandidates) + { + registry.fill(HIST("hNCand"), localCandidates.size()); + + for (const auto& cand1 : localCandidates) { + auto mass1 = cand1.m(); + for (auto cand2 = cand1 + 1; cand2 != localCandidates.end(); ++cand2) { + auto mass2 = cand2.m(); + registry.fill(HIST("hMassDMesonPair"), mass2, mass1); + } + } + } + PROCESS_SWITCH(HfTaskCorrelationDplusDplusReduced, processLocalData, "Process local data", true); + + void processLocalDataMcRec(o2::aod::HfCandDpFullEvs::iterator const&, + SelectedCandidates const& localCandidates) + { + registry.fill(HIST("hNMcRec"), localCandidates.size()); + + for (const auto& cand1 : localCandidates) { + auto mass1 = cand1.m(); + registry.fill(HIST("hMassDplus"), mass1); + if (std::abs(cand1.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) + registry.fill(HIST("hMassDplusMatched"), mass1); + } + } + PROCESS_SWITCH(HfTaskCorrelationDplusDplusReduced, processLocalDataMcRec, "Process local MC data", false); + + void processLocalDataMcGen(o2::aod::HfCandDpMcEvs::iterator const&, + SelectedMcParticles const& localMcParticles) + { + registry.fill(HIST("hNMcGen"), localMcParticles.size()); + + for (const auto& part1 : localMcParticles) { + for (auto part2 = part1 + 1; part2 != localMcParticles.end(); ++part2) { + registry.fill(HIST("hDltPhiMcGen"), part2.phi() - part1.phi()); + } + } + } + PROCESS_SWITCH(HfTaskCorrelationDplusDplusReduced, processLocalDataMcGen, "Process local MC data at the gen level", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +}