|
| 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 treeCreatorB0ToDPi.cxx |
| 13 | +/// \brief Writer of B0 → D- π+ candidates in the form of flat tables to be stored in TTrees. |
| 14 | +/// Intended for debug, local optimization of analysis on small samples or ML training. |
| 15 | +/// In this file are defined and filled the output tables |
| 16 | +/// |
| 17 | +/// \author Alexandre Bigot <alexandre.bigot@cern.ch>, IPHC Strasbourg |
| 18 | + |
| 19 | +#include "Framework/AnalysisTask.h" |
| 20 | +#include "Framework/runDataProcessing.h" |
| 21 | + |
| 22 | +#include "PWGHF/DataModel/CandidateReconstructionTables.h" |
| 23 | +#include "PWGHF/DataModel/CandidateSelectionTables.h" |
| 24 | + |
| 25 | +using namespace o2; |
| 26 | +using namespace o2::framework; |
| 27 | +using namespace o2::framework::expressions; |
| 28 | +using namespace o2::aod::hf_cand_b0; |
| 29 | +using namespace o2::aod::hf_sel_candidate_b0; |
| 30 | + |
| 31 | +namespace o2::aod |
| 32 | +{ |
| 33 | +namespace full |
| 34 | +{ |
| 35 | +DECLARE_SOA_COLUMN(RSecondaryVertex, rSecondaryVertex, float); //! Radius of secondary vertex (cm) |
| 36 | +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of prong0 (GeV/c) |
| 37 | +DECLARE_SOA_COLUMN(PProng0, pProng0, float); //! Momentum of prong0 (GeV/c) |
| 38 | +DECLARE_SOA_COLUMN(ImpactParameterNormalised0, impactParameterNormalised0, float); //! Normalised impact parameter of prong0 |
| 39 | +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of prong1 (GeV/c) |
| 40 | +DECLARE_SOA_COLUMN(PProng1, pProng1, float); //! Momentum of prong1 (in GeV/c) |
| 41 | +DECLARE_SOA_COLUMN(ImpactParameterNormalised1, impactParameterNormalised1, float); //! Normalised impact parameter of prong1 |
| 42 | +DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int); //! Selection flag of candidate (output of candidateSelector) |
| 43 | +DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) |
| 44 | +DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) |
| 45 | +DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) |
| 46 | +DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate |
| 47 | +DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate |
| 48 | +DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate |
| 49 | +DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) |
| 50 | +DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); //! TPC Nsigma separation for prong1 with pion mass hypothesis |
| 51 | +DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF Nsigma separation for prong1 with pion mass hypothesis |
| 52 | +DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length of candidate (cm) |
| 53 | +DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Transverse decay length of candidate (cm) |
| 54 | +DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! Normalised decay length of candidate |
| 55 | +DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! Normalised transverse decay length of candidate |
| 56 | +DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine pointing angle of candidate |
| 57 | +DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine pointing angle of candidate in transverse plane |
| 58 | +DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs |
| 59 | +DECLARE_SOA_COLUMN(Ct, ct, float); //! Proper lifetime times c of candidate (cm) |
| 60 | +// Events |
| 61 | +DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); //! Event rejection flag |
| 62 | +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); //! Run number |
| 63 | +} // namespace full |
| 64 | + |
| 65 | +DECLARE_SOA_TABLE(HfCandB0Lite, "AOD", "HFCANDB0Lite", |
| 66 | + hf_cand::Chi2PCA, |
| 67 | + full::DecayLength, |
| 68 | + full::DecayLengthXY, |
| 69 | + full::DecayLengthNormalised, |
| 70 | + full::DecayLengthXYNormalised, |
| 71 | + full::PtProng0, |
| 72 | + full::PtProng1, |
| 73 | + hf_cand::ImpactParameter0, |
| 74 | + hf_cand::ImpactParameter1, |
| 75 | + full::NSigTpcPi1, |
| 76 | + full::NSigTofPi1, |
| 77 | + full::CandidateSelFlag, |
| 78 | + full::M, |
| 79 | + full::Pt, |
| 80 | + full::Cpa, |
| 81 | + full::CpaXY, |
| 82 | + full::MaxNormalisedDeltaIP, |
| 83 | + full::Eta, |
| 84 | + full::Phi, |
| 85 | + full::Y, |
| 86 | + hf_cand_3prong::FlagMcMatchRec, |
| 87 | + hf_cand_3prong::OriginMcRec); |
| 88 | + |
| 89 | +DECLARE_SOA_TABLE(HfCandB0Full, "AOD", "HFCANDB0Full", |
| 90 | + collision::BCId, |
| 91 | + collision::NumContrib, |
| 92 | + collision::PosX, |
| 93 | + collision::PosY, |
| 94 | + collision::PosZ, |
| 95 | + hf_cand::XSecondaryVertex, |
| 96 | + hf_cand::YSecondaryVertex, |
| 97 | + hf_cand::ZSecondaryVertex, |
| 98 | + hf_cand::ErrorDecayLength, |
| 99 | + hf_cand::ErrorDecayLengthXY, |
| 100 | + hf_cand::Chi2PCA, |
| 101 | + full::RSecondaryVertex, |
| 102 | + full::DecayLength, |
| 103 | + full::DecayLengthXY, |
| 104 | + full::DecayLengthNormalised, |
| 105 | + full::DecayLengthXYNormalised, |
| 106 | + full::ImpactParameterNormalised0, |
| 107 | + full::PtProng0, |
| 108 | + full::PProng0, |
| 109 | + full::ImpactParameterNormalised1, |
| 110 | + full::PtProng1, |
| 111 | + full::PProng1, |
| 112 | + hf_cand::PxProng0, |
| 113 | + hf_cand::PyProng0, |
| 114 | + hf_cand::PzProng0, |
| 115 | + hf_cand::PxProng1, |
| 116 | + hf_cand::PyProng1, |
| 117 | + hf_cand::PzProng1, |
| 118 | + hf_cand::ImpactParameter0, |
| 119 | + hf_cand::ImpactParameter1, |
| 120 | + hf_cand::ErrorImpactParameter0, |
| 121 | + hf_cand::ErrorImpactParameter1, |
| 122 | + full::NSigTpcPi1, |
| 123 | + full::NSigTofPi1, |
| 124 | + full::CandidateSelFlag, |
| 125 | + full::M, |
| 126 | + full::Pt, |
| 127 | + full::P, |
| 128 | + full::Cpa, |
| 129 | + full::CpaXY, |
| 130 | + full::MaxNormalisedDeltaIP, |
| 131 | + full::Ct, |
| 132 | + full::Eta, |
| 133 | + full::Phi, |
| 134 | + full::Y, |
| 135 | + full::E, |
| 136 | + hf_cand_3prong::FlagMcMatchRec, |
| 137 | + hf_cand_3prong::OriginMcRec); |
| 138 | + |
| 139 | +DECLARE_SOA_TABLE(HfCandB0FullEvents, "AOD", "HFCANDB0FullE", |
| 140 | + collision::BCId, |
| 141 | + collision::NumContrib, |
| 142 | + collision::PosX, |
| 143 | + collision::PosY, |
| 144 | + collision::PosZ, |
| 145 | + full::IsEventReject, |
| 146 | + full::RunNumber); |
| 147 | + |
| 148 | +DECLARE_SOA_TABLE(HfCandB0FullParticles, "AOD", "HFCANDB0FullP", |
| 149 | + collision::BCId, |
| 150 | + full::Pt, |
| 151 | + full::Eta, |
| 152 | + full::Phi, |
| 153 | + full::Y, |
| 154 | + hf_cand_3prong::FlagMcMatchRec, |
| 155 | + hf_cand_3prong::OriginMcGen); |
| 156 | +} // namespace o2::aod |
| 157 | + |
| 158 | +/// Writes the full information in an output TTree |
| 159 | +struct HfTreeCreatorB0ToDPi { |
| 160 | + Produces<o2::aod::HfCandB0Full> rowCandidateFull; |
| 161 | + Produces<o2::aod::HfCandB0FullEvents> rowCandidateFullEvents; |
| 162 | + Produces<o2::aod::HfCandB0FullParticles> rowCandidateFullParticles; |
| 163 | + Produces<o2::aod::HfCandB0Lite> rowCandidateLite; |
| 164 | + |
| 165 | + Configurable<int> selectionFlagB0{"selectionB0", 1, "Selection Flag for B0"}; |
| 166 | + Configurable<bool> fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"}; |
| 167 | + |
| 168 | + // parameters for production of training samples |
| 169 | + Configurable<bool> fillOnlySignal{"fillOnlySignal", false, "Flag to fill derived tables with signal for ML trainings"}; |
| 170 | + Configurable<bool> fillOnlyBackground{"fillOnlyBackground", false, "Flag to fill derived tables with background for ML trainings"}; |
| 171 | + Configurable<float> downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"}; |
| 172 | + Configurable<float> ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"}; |
| 173 | + |
| 174 | + using SelectedCandidatesMc = soa::Filtered<soa::Join<aod::HfCandB0, aod::HfCandB0McRec, aod::HfSelB0ToDPi>>; |
| 175 | + |
| 176 | + Filter filterSelectCandidates = aod::hf_sel_candidate_b0::isSelB0ToDPi >= selectionFlagB0; |
| 177 | + |
| 178 | + Partition<SelectedCandidatesMc> recSig = nabs(aod::hf_cand_b0::flagMcMatchRec) == (int8_t)BIT(aod::hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi); |
| 179 | + Partition<SelectedCandidatesMc> recBg = nabs(aod::hf_cand_b0::flagMcMatchRec) != (int8_t)BIT(aod::hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi); |
| 180 | + |
| 181 | + void init(InitContext const&) |
| 182 | + { |
| 183 | + } |
| 184 | + |
| 185 | + template <typename T> |
| 186 | + void fillEvent(const T& collision, int isEventReject, int runNumber) |
| 187 | + { |
| 188 | + rowCandidateFullEvents( |
| 189 | + collision.bcId(), |
| 190 | + collision.numContrib(), |
| 191 | + collision.posX(), |
| 192 | + collision.posY(), |
| 193 | + collision.posZ(), |
| 194 | + isEventReject, |
| 195 | + runNumber); |
| 196 | + } |
| 197 | + |
| 198 | + template <bool doMc = false, typename T, typename U> |
| 199 | + void fillCandidateTable(const T& candidate, const U& prong1) |
| 200 | + { |
| 201 | + int8_t flagMc = 0; |
| 202 | + int8_t originMc = 0; |
| 203 | + if constexpr (doMc) { |
| 204 | + flagMc = candidate.flagMcMatchRec(); |
| 205 | + originMc = candidate.originMcRec(); |
| 206 | + } |
| 207 | + if (fillCandidateLiteTable) { |
| 208 | + rowCandidateLite( |
| 209 | + candidate.chi2PCA(), |
| 210 | + candidate.decayLength(), |
| 211 | + candidate.decayLengthXY(), |
| 212 | + candidate.decayLengthNormalised(), |
| 213 | + candidate.decayLengthXYNormalised(), |
| 214 | + candidate.ptProng0(), |
| 215 | + candidate.ptProng1(), |
| 216 | + candidate.impactParameter0(), |
| 217 | + candidate.impactParameter1(), |
| 218 | + prong1.tpcNSigmaPi(), |
| 219 | + prong1.tofNSigmaPi(), |
| 220 | + candidate.isSelB0ToDPi(), |
| 221 | + invMassB0ToDPi(candidate), |
| 222 | + candidate.pt(), |
| 223 | + candidate.cpa(), |
| 224 | + candidate.cpaXY(), |
| 225 | + candidate.maxNormalisedDeltaIP(), |
| 226 | + candidate.eta(), |
| 227 | + candidate.phi(), |
| 228 | + yB0(candidate), |
| 229 | + flagMc, |
| 230 | + originMc); |
| 231 | + } else { |
| 232 | + rowCandidateFull( |
| 233 | + prong1.collision().bcId(), |
| 234 | + prong1.collision().numContrib(), |
| 235 | + candidate.posX(), |
| 236 | + candidate.posY(), |
| 237 | + candidate.posZ(), |
| 238 | + candidate.xSecondaryVertex(), |
| 239 | + candidate.ySecondaryVertex(), |
| 240 | + candidate.zSecondaryVertex(), |
| 241 | + candidate.errorDecayLength(), |
| 242 | + candidate.errorDecayLengthXY(), |
| 243 | + candidate.chi2PCA(), |
| 244 | + candidate.rSecondaryVertex(), |
| 245 | + candidate.decayLength(), |
| 246 | + candidate.decayLengthXY(), |
| 247 | + candidate.decayLengthNormalised(), |
| 248 | + candidate.decayLengthXYNormalised(), |
| 249 | + candidate.impactParameterNormalised0(), |
| 250 | + candidate.ptProng0(), |
| 251 | + RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), |
| 252 | + candidate.impactParameterNormalised1(), |
| 253 | + candidate.ptProng1(), |
| 254 | + RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()), |
| 255 | + candidate.pxProng0(), |
| 256 | + candidate.pyProng0(), |
| 257 | + candidate.pzProng0(), |
| 258 | + candidate.pxProng1(), |
| 259 | + candidate.pyProng1(), |
| 260 | + candidate.pzProng1(), |
| 261 | + candidate.impactParameter0(), |
| 262 | + candidate.impactParameter1(), |
| 263 | + candidate.errorImpactParameter0(), |
| 264 | + candidate.errorImpactParameter1(), |
| 265 | + prong1.tpcNSigmaPi(), |
| 266 | + prong1.tofNSigmaPi(), |
| 267 | + candidate.isSelB0ToDPi(), |
| 268 | + invMassB0ToDPi(candidate), |
| 269 | + candidate.pt(), |
| 270 | + candidate.p(), |
| 271 | + candidate.cpa(), |
| 272 | + candidate.cpaXY(), |
| 273 | + candidate.maxNormalisedDeltaIP(), |
| 274 | + ctB0(candidate), |
| 275 | + candidate.eta(), |
| 276 | + candidate.phi(), |
| 277 | + yB0(candidate), |
| 278 | + eB0(candidate), |
| 279 | + flagMc, |
| 280 | + originMc); |
| 281 | + } |
| 282 | + } |
| 283 | + |
| 284 | + void processData(aod::Collisions const& collisions, |
| 285 | + soa::Filtered<soa::Join<aod::HfCandB0, aod::HfSelB0ToDPi>> const& candidates, |
| 286 | + aod::BigTracksPID const&) |
| 287 | + { |
| 288 | + // Filling event properties |
| 289 | + rowCandidateFullEvents.reserve(collisions.size()); |
| 290 | + for (auto const& collision : collisions) { |
| 291 | + fillEvent(collision, 0, 1); |
| 292 | + } |
| 293 | + |
| 294 | + // Filling candidate properties |
| 295 | + rowCandidateFull.reserve(candidates.size()); |
| 296 | + if (fillCandidateLiteTable) { |
| 297 | + rowCandidateLite.reserve(candidates.size()); |
| 298 | + } |
| 299 | + for (auto const& candidate : candidates) { |
| 300 | + if (fillOnlyBackground) { |
| 301 | + float pseudoRndm = candidate.ptProng1() * 1000. - (int64_t)(candidate.ptProng1() * 1000); |
| 302 | + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { |
| 303 | + continue; |
| 304 | + } |
| 305 | + } |
| 306 | + auto prong1 = candidate.prong1_as<aod::BigTracksPID>(); |
| 307 | + fillCandidateTable(candidate, prong1); |
| 308 | + } |
| 309 | + } |
| 310 | + |
| 311 | + PROCESS_SWITCH(HfTreeCreatorB0ToDPi, processData, "Process data", true); |
| 312 | + |
| 313 | + void processMc(aod::Collisions const& collisions, |
| 314 | + aod::McCollisions const&, |
| 315 | + SelectedCandidatesMc const& candidates, |
| 316 | + soa::Join<aod::McParticles, aod::HfCandB0McGen> const& particles, |
| 317 | + aod::BigTracksPID const&) |
| 318 | + { |
| 319 | + // Filling event properties |
| 320 | + rowCandidateFullEvents.reserve(collisions.size()); |
| 321 | + for (auto const& collision : collisions) { |
| 322 | + fillEvent(collision, 0, 1); |
| 323 | + } |
| 324 | + |
| 325 | + // Filling candidate properties |
| 326 | + if (fillOnlySignal) { |
| 327 | + rowCandidateFull.reserve(recSig.size()); |
| 328 | + if (fillCandidateLiteTable) { |
| 329 | + rowCandidateLite.reserve(recSig.size()); |
| 330 | + } |
| 331 | + for (const auto& candidate : recSig) { |
| 332 | + auto prong1 = candidate.prong1_as<aod::BigTracksPID>(); |
| 333 | + fillCandidateTable<true>(candidate, prong1); |
| 334 | + } |
| 335 | + } else if (fillOnlyBackground) { |
| 336 | + rowCandidateFull.reserve(recBg.size()); |
| 337 | + if (fillCandidateLiteTable) { |
| 338 | + rowCandidateLite.reserve(recBg.size()); |
| 339 | + } |
| 340 | + for (const auto& candidate : recBg) { |
| 341 | + float pseudoRndm = candidate.ptProng1() * 1000. - (int64_t)(candidate.ptProng1() * 1000); |
| 342 | + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { |
| 343 | + continue; |
| 344 | + } |
| 345 | + auto prong1 = candidate.prong1_as<aod::BigTracksPID>(); |
| 346 | + fillCandidateTable<true>(candidate, prong1); |
| 347 | + } |
| 348 | + } else { |
| 349 | + rowCandidateFull.reserve(candidates.size()); |
| 350 | + if (fillCandidateLiteTable) { |
| 351 | + rowCandidateLite.reserve(candidates.size()); |
| 352 | + } |
| 353 | + for (const auto& candidate : candidates) { |
| 354 | + auto prong1 = candidate.prong1_as<aod::BigTracksPID>(); |
| 355 | + fillCandidateTable<true>(candidate, prong1); |
| 356 | + } |
| 357 | + } |
| 358 | + |
| 359 | + // Filling particle properties |
| 360 | + rowCandidateFullParticles.reserve(particles.size()); |
| 361 | + for (auto const& particle : particles) { |
| 362 | + if (TESTBIT(std::abs(particle.flagMcMatchGen()), DecayTypeMc::B0ToDplusPiToPiKPiPi)) { |
| 363 | + rowCandidateFullParticles( |
| 364 | + particle.mcCollision().bcId(), |
| 365 | + particle.pt(), |
| 366 | + particle.eta(), |
| 367 | + particle.phi(), |
| 368 | + RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())), |
| 369 | + particle.flagMcMatchGen(), |
| 370 | + particle.originMcGen()); |
| 371 | + } |
| 372 | + } |
| 373 | + } |
| 374 | + |
| 375 | + PROCESS_SWITCH(HfTreeCreatorB0ToDPi, processMc, "Process MC", false); |
| 376 | +}; |
| 377 | + |
| 378 | +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) |
| 379 | +{ |
| 380 | + return WorkflowSpec{adaptAnalysisTask<HfTreeCreatorB0ToDPi>(cfgc)}; |
| 381 | +} |
0 commit comments