|
| 1 | +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. |
| 2 | +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. |
| 3 | +// All rights not expressly granted are reserved. |
| 4 | +// |
| 5 | +// This software is distributed under the terms of the GNU General Public |
| 6 | +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". |
| 7 | +// |
| 8 | +// In applying this license CERN does not waive the privileges and immunities |
| 9 | +// granted to it by virtue of its status as an Intergovernmental Organization |
| 10 | +// or submit itself to any jurisdiction. |
| 11 | + |
| 12 | +/// \file taskomegac0ToOmegapi.cxx |
| 13 | +/// \brief OmegaC0 analysis task |
| 14 | +/// |
| 15 | +/// \author Yunfan Liu <[email protected]>, China University of Geosciences |
| 16 | + |
| 17 | + |
| 18 | +#include <vector> |
| 19 | + |
| 20 | +#include "CommonConstants/PhysicsConstants.h" |
| 21 | +#include "Framework/AnalysisTask.h" |
| 22 | +#include "Framework/HistogramRegistry.h" |
| 23 | +#include "Framework/runDataProcessing.h" |
| 24 | + |
| 25 | +#include "PWGHF/Core/CentralityEstimation.h" |
| 26 | +#include "PWGHF/Core/HfHelper.h" |
| 27 | +#include "PWGHF/DataModel/CandidateReconstructionTables.h" |
| 28 | +#include "PWGHF/DataModel/CandidateSelectionTables.h" |
| 29 | +#include "PWGHF/Utils/utilsEvSelHf.h" |
| 30 | +// #include "PWGHF/Utils/utilsAnalysis.h" |
| 31 | + |
| 32 | +using namespace o2; |
| 33 | +using namespace o2::analysis; |
| 34 | +using namespace o2::framework; |
| 35 | +using namespace o2::framework::expressions; |
| 36 | + |
| 37 | +/// Omegac0 analysis task |
| 38 | + |
| 39 | +struct HfTaskOmegac0 { |
| 40 | + Configurable<double> yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; |
| 41 | + Configurable<double> yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; |
| 42 | + Configurable<int> selectionFlagHf{"selectionFlagHf", 1, "Selection Flag for HF flagged candidates"}; |
| 43 | + |
| 44 | + // ML inference |
| 45 | + Configurable<bool> applyMl{"applyMl", false, "Flag to apply ML selections"}; |
| 46 | + |
| 47 | + // ThnSparse for ML outputScores and Vars |
| 48 | + ConfigurableAxis thnConfigAxisPromptScore{"thnConfigAxisPromptScore", {50, 0, 1}, "Prompt score bins"}; |
| 49 | + ConfigurableAxis thnConfigAxisMass{"thnConfigAxisMass", {120, 1.5848, 2.1848}, "Cand. inv-mass bins"}; |
| 50 | + ConfigurableAxis thnConfigAxisPtB{"thnConfigAxisPtB", {1000, 0, 100}, "Cand. beauty mother pTB bins"}; |
| 51 | + ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {500, 0, 50}, "Cand. pT bins"}; |
| 52 | + ConfigurableAxis thnConfigAxisY{"thnConfigAxisY", {20, -1, 1}, "Cand. rapidity bins"}; |
| 53 | + ConfigurableAxis thnConfigAxisOrigin{"thnConfigAxisOrigin", {3, -0.5, 2.5}, "Cand. origin type"}; |
| 54 | + ConfigurableAxis thnConfigAxisCandType{"thnConfigAxisCandType", {6, -0.5, 5.5}, "Omegac0 type"}; |
| 55 | + ConfigurableAxis thnConfigAxisGenPtD{"thnConfigAxisGenPtD", {500, 0, 50}, "Gen Pt D"}; |
| 56 | + ConfigurableAxis thnConfigAxisGenPtB{"thnConfigAxisGenPtB", {1000, 0, 100}, "Gen Pt B"}; |
| 57 | + ConfigurableAxis thnConfigAxisNumPvContr{"thnConfigAxisNumPvContr", {200, -0.5, 199.5}, "Number of PV contributors"}; |
| 58 | + |
| 59 | + |
| 60 | + HfHelper hfHelper; |
| 61 | + using MyTracksWMc = soa::Join<aod::Tracks, aod::TracksIU, aod::McTrackLabels>; |
| 62 | + |
| 63 | + using Omegac0Candidates = soa::Join<aod::HfCandToOmegaPi, aod::HfSelToOmegaPi>; |
| 64 | + using Omegac0CandidatesKF = soa::Join<Omegac0Candidates, aod::HfOmegacKf>; |
| 65 | + using OmegaC0CandidatesMcKF = soa::Join<Omegac0CandidatesKF, aod::HfToOmegaPiMCRec>; |
| 66 | + |
| 67 | + using Omegac0CandidatesMl = soa::Join<aod::HfCandToOmegaPi, aod::HfMlSelOmegacToOmegaPi>; |
| 68 | + using Omegac0CandidatesMlKF = soa::Join<Omegac0CandidatesMl, aod::HfOmegacKf>; |
| 69 | + using Omegac0CandidatesMlMcKF = soa::Join<Omegac0CandidatesMlKF, aod::HfToOmegaPiMCRec>; |
| 70 | + |
| 71 | + using Collisions = soa::Join<aod::Collisions, aod::EvSels>; |
| 72 | + using CollisionsWithMcLabels = soa::Join<aod::Collisions, aod::McCollisionLabels, aod::EvSels>; |
| 73 | + PresliceUnsorted<CollisionsWithMcLabels> colPerMcCollision = aod::mccollisionlabel::mcCollisionId; |
| 74 | + SliceCache cache; |
| 75 | + |
| 76 | + |
| 77 | + HistogramRegistry registry{ |
| 78 | + "registry", |
| 79 | + {}}; |
| 80 | + |
| 81 | + void init(InitContext&) |
| 82 | + { |
| 83 | + std::array<bool, 12> doprocess{ doprocessDataWithKFParticle, doprocessMcWithKFParticle, doprocessDataWithKFParticleMl, doprocessMcWithKFParticleMl}; |
| 84 | + if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) == 0) { |
| 85 | + LOGP(fatal, "At least one process function should be enabled at a time."); |
| 86 | + } |
| 87 | + |
| 88 | + const AxisSpec thnAxisMass{thnConfigAxisMass, "inv. mass (#pi K) (GeV/#it{c}^{2})"}; |
| 89 | + const AxisSpec thnAxisPt{thnConfigAxisPt, "#it{p}_{T} (GeV/#it{c})"}; |
| 90 | + const AxisSpec thnAxisPtB{thnConfigAxisPtB, "#it{p}_{T}^{B} (GeV/#it{c})"}; |
| 91 | + const AxisSpec thnAxisY{thnConfigAxisY, "y"}; |
| 92 | + const AxisSpec thnAxisOrigin{thnConfigAxisOrigin, "Origin"}; |
| 93 | + const AxisSpec thnAxisGenPtD{thnConfigAxisGenPtD, "#it{p}_{T} (GeV/#it{c})"}; |
| 94 | + const AxisSpec thnAxisGenPtB{thnConfigAxisGenPtB, "#it{p}_{T}^{B} (GeV/#it{c})"}; |
| 95 | + const AxisSpec thnAxisNumPvContr{thnConfigAxisNumPvContr, "Number of PV contributors"}; |
| 96 | + |
| 97 | + if ( doprocessMcWithKFParticle || doprocessMcWithKFParticleMl) { |
| 98 | + std::vector<AxisSpec> axesAcc = {thnAxisGenPtD, thnAxisGenPtB, thnAxisY, thnAxisOrigin, thnAxisNumPvContr}; |
| 99 | + registry.add("hSparseAcc", "Thn for generated Omega0 from charm and beauty", HistType::kTHnSparseD, axesAcc); |
| 100 | + registry.get<THnSparse>(HIST("hSparseAcc"))->Sumw2(); |
| 101 | + } |
| 102 | + |
| 103 | + std::vector<AxisSpec> axes = {thnAxisMass, thnAxisPt, thnAxisY,}; |
| 104 | + if ( doprocessMcWithKFParticle|| doprocessMcWithKFParticleMl) { |
| 105 | + axes.push_back(thnAxisPtB); |
| 106 | + axes.push_back(thnAxisOrigin); |
| 107 | + axes.push_back(thnAxisNumPvContr); |
| 108 | + } |
| 109 | + if (applyMl) { |
| 110 | + const AxisSpec thnAxisPromptScore{thnConfigAxisPromptScore, "BDT score prompt."}; |
| 111 | + |
| 112 | + axes.insert(axes.begin(), thnAxisPromptScore); |
| 113 | + |
| 114 | + registry.add("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsOmegac0Type", "Thn for Omegac0 candidates", HistType::kTHnSparseD, axes); |
| 115 | + registry.get<THnSparse>(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsOmegac0Type"))->Sumw2(); |
| 116 | + } else { |
| 117 | + registry.add("hMassVsPtVsPtBVsYVsOriginVsOmegac0Type", "Thn for Omegac0 candidates", HistType::kTHnSparseD, axes); |
| 118 | + registry.get<THnSparse>(HIST("hMassVsPtVsPtBVsYVsOriginVsOmegac0Type"))->Sumw2(); |
| 119 | + } |
| 120 | + } |
| 121 | + |
| 122 | + template <bool applyMl, typename CandType, typename CollType> |
| 123 | + void processData(const CandType& candidates, CollType const&) |
| 124 | + { |
| 125 | + for (const auto& candidate : candidates) { |
| 126 | + if (!(candidate.hfflag() & 1 << aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi)) { |
| 127 | + continue; |
| 128 | + } |
| 129 | + if (yCandRecoMax >= 0. && std::abs(candidate.kfRapOmegac()) > yCandRecoMax) { |
| 130 | + continue; |
| 131 | + } |
| 132 | + float massOmegac0; |
| 133 | + massOmegac0 = candidate.invMassCharmBaryon(); |
| 134 | + auto rapidityCandidate = candidate.kfRapOmegac(); |
| 135 | + auto ptCandidate = candidate.ptCharmBaryon(); |
| 136 | + if constexpr (applyMl) { |
| 137 | + registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsOmegac0Type"), candidate.mlProbOmegac()[0], massOmegac0, ptCandidate, rapidityCandidate); |
| 138 | + } else { |
| 139 | + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsOmegac0Type"), massOmegac0, ptCandidate, rapidityCandidate); |
| 140 | + } |
| 141 | + } |
| 142 | + } |
| 143 | + |
| 144 | + void processDataWithKFParticle(Omegac0CandidatesKF const& omegac0CandidatesKF, Collisions const& collisions) |
| 145 | + { |
| 146 | + processData<false>(omegac0CandidatesKF, collisions); |
| 147 | + } |
| 148 | + PROCESS_SWITCH(HfTaskOmegac0, processDataWithKFParticle, "process taskOmegac0 with KFParticle", false); |
| 149 | + // TODO: add processKFParticleCent |
| 150 | + |
| 151 | + void processDataWithKFParticleMl(Omegac0CandidatesMlKF const&omegac0CandidatesMlKF, Collisions const& collisions) |
| 152 | + { |
| 153 | + processData<true>(omegac0CandidatesMlKF, collisions); |
| 154 | + } |
| 155 | + PROCESS_SWITCH(HfTaskOmegac0, processDataWithKFParticleMl, "process taskOmegac0 with KFParticle and ML selections", false); |
| 156 | + // TODO: add processKFParticleMlCent |
| 157 | + |
| 158 | + template <bool applyMl, typename CandType, typename CollType> |
| 159 | + void processMc(const CandType& candidates, |
| 160 | + soa::Join<aod::McParticles, aod::HfToOmegaPiMCGen> const& mcParticles, |
| 161 | + MyTracksWMc const&, |
| 162 | + CollType const& collisions, |
| 163 | + aod::McCollisions const&) |
| 164 | + { |
| 165 | + // MC rec. |
| 166 | + for (const auto& candidate : candidates) { |
| 167 | + if (!(candidate.hfflag() & 1 << aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi)) { |
| 168 | + continue; |
| 169 | + } |
| 170 | + if (yCandRecoMax >= 0. && std::abs(candidate.kfRapOmegac()) > yCandRecoMax) { |
| 171 | + continue; |
| 172 | + } |
| 173 | + auto collision = candidate.template collision_as<CollType>(); |
| 174 | + auto numPvContributors = collision.numContrib(); |
| 175 | + float massOmegac0; |
| 176 | + massOmegac0 = candidate.invMassCharmBaryon(); |
| 177 | + auto ptCandidate = candidate.ptCharmBaryon(); |
| 178 | + auto rapidityCandidate = candidate.kfRapOmegac(); |
| 179 | + |
| 180 | + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi)) { |
| 181 | + if constexpr (applyMl) { |
| 182 | + registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsOmegac0Type"), candidate.mlProbOmegac()[0], massOmegac0, ptCandidate, rapidityCandidate, candidate.ptBhadMotherPart(), candidate.originRec(), numPvContributors); |
| 183 | + |
| 184 | + } else { |
| 185 | + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsOmegac0Type"), massOmegac0, ptCandidate, rapidityCandidate, candidate.ptBhadMotherPart(), candidate.originRec(), numPvContributors); |
| 186 | + } |
| 187 | + } |
| 188 | + } |
| 189 | + // MC gen. |
| 190 | + for (const auto& particle : mcParticles) { |
| 191 | + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi) { |
| 192 | + if (yCandGenMax >= 0. && std::abs(particle.rapidityCharmBaryonGen()) > yCandGenMax) { |
| 193 | + continue; |
| 194 | + } |
| 195 | + float ptGenB = -1; |
| 196 | + auto ptGen = particle.pt(); |
| 197 | + auto yGen = particle.rapidityCharmBaryonGen(); |
| 198 | + registry.fill(HIST("hPtGen"), ptGen); |
| 199 | + registry.fill(HIST("hPtVsYGen"), ptGen, yGen); |
| 200 | + |
| 201 | + unsigned maxNumContrib = 0; |
| 202 | + const auto& recoCollsPerMcColl = collisions.sliceBy(colPerMcCollision, particle.mcCollision().globalIndex()); |
| 203 | + for (const auto& recCol : recoCollsPerMcColl) { |
| 204 | + maxNumContrib = recCol.numContrib() > maxNumContrib ? recCol.numContrib() : maxNumContrib; |
| 205 | + } |
| 206 | + |
| 207 | + |
| 208 | + if (particle.originGen() == RecoDecay::OriginType::Prompt) { |
| 209 | + registry.fill(HIST("hSparseAcc"), ptGen, ptGenB, yGen, 1, maxNumContrib); |
| 210 | + |
| 211 | + } else { |
| 212 | + ptGenB = mcParticles.rawIteratorAt(particle.idxBhadMotherPart()).pt(); |
| 213 | + registry.fill(HIST("hSparseAcc"), ptGen, ptGenB, yGen, 2, maxNumContrib); |
| 214 | + } |
| 215 | + } |
| 216 | + } |
| 217 | + } |
| 218 | + |
| 219 | + void processMcWithKFParticle(OmegaC0CandidatesMcKF const&omegaC0CandidatesMcKF, |
| 220 | + soa::Join<aod::McParticles, aod::HfToOmegaPiMCGen> const& mcParticles, |
| 221 | + MyTracksWMc const& tracks, |
| 222 | + CollisionsWithMcLabels const& collisions, |
| 223 | + aod::McCollisions const& mcCollisions) |
| 224 | + { |
| 225 | + processMc<false>(omegaC0CandidatesMcKF, mcParticles, tracks, collisions, mcCollisions); |
| 226 | + } |
| 227 | + PROCESS_SWITCH(HfTaskOmegac0, processMcWithKFParticle, "Process MC with KFParticle", false); |
| 228 | + // TODO: add the processMcWithKFParticleCent |
| 229 | + |
| 230 | + void processMcWithKFParticleMl(Omegac0CandidatesMlMcKF const& omegac0CandidatesMlMcKF, |
| 231 | + soa::Join<aod::McParticles, aod::HfToOmegaPiMCGen> const& mcParticles, |
| 232 | + MyTracksWMc const& tracks, |
| 233 | + CollisionsWithMcLabels const& collisions, |
| 234 | + aod::McCollisions const& mcCollisions) |
| 235 | + { |
| 236 | + processMc<true>(omegac0CandidatesMlMcKF, mcParticles, tracks, collisions, mcCollisions); |
| 237 | + } |
| 238 | + PROCESS_SWITCH(HfTaskOmegac0, processMcWithKFParticleMl, "Process MC with KFParticle and ML selections", false); |
| 239 | + // TODO: add the processMcWithKFParticleMlCent |
| 240 | +}; |
| 241 | + |
| 242 | +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) |
| 243 | +{ |
| 244 | + return WorkflowSpec{adaptAnalysisTask<HfTaskOmegac0>(cfgc)}; |
| 245 | +} |
0 commit comments