diff --git a/PWGCF/Femto/Core/baseSelection.h b/PWGCF/Femto/Core/baseSelection.h index 5c46c4747a3..8ddc97e3da1 100644 --- a/PWGCF/Femto/Core/baseSelection.h +++ b/PWGCF/Femto/Core/baseSelection.h @@ -165,12 +165,12 @@ class BaseSelection std::string const& selectionName, int mode) { + int selectionMode = mode; + if (mPassThrough) { - mSelectionContainers.at(observableIndex) = selectioncontainer::SelectionContainer(selectionName, std::vector{1}, limits::LimitType::kEqual, false, false, false); - return; + selectionMode = 2; } - - switch (mode) { + switch (selectionMode) { case -1: // cut is optional and we store a bit for it mSelectionContainers.at(observableIndex) = selectioncontainer::SelectionContainer(selectionName, std::vector{1}, limits::LimitType::kEqual, false, false, true); break; diff --git a/PWGCF/Femto/Core/cascadeBuilder.h b/PWGCF/Femto/Core/cascadeBuilder.h index 1cd12cc1c7b..a697a877a63 100644 --- a/PWGCF/Femto/Core/cascadeBuilder.h +++ b/PWGCF/Femto/Core/cascadeBuilder.h @@ -619,20 +619,20 @@ class CascadeBuilder collisionBuilder.template fillMcCollision(collisionProducts, col, mcCols, mcProducts, mcBuilder); auto bachelor = cascade.template bachelor_as(); - bachelorIndex = trackBuilder.template getDaughterIndex(col, collisionBuilder, mcCols, bachelor, trackProducts, mcParticles, mcBuilder, mcProducts); + bachelorIndex = trackBuilder.template getDaughterIndex(bachelor, trackProducts, mcCols, collisionBuilder, mcParticles, mcBuilder, mcProducts); auto posDaughter = cascade.template posTrack_as(); - posDaughterIndex = trackBuilder.template getDaughterIndex(col, collisionBuilder, mcCols, posDaughter, trackProducts, mcParticles, mcBuilder, mcProducts); + posDaughterIndex = trackBuilder.template getDaughterIndex(posDaughter, trackProducts, mcCols, collisionBuilder, mcParticles, mcBuilder, mcProducts); auto negDaughter = cascade.template negTrack_as(); - negDaughterIndex = trackBuilder.template getDaughterIndex(col, collisionBuilder, mcCols, negDaughter, trackProducts, mcParticles, mcBuilder, mcProducts); + negDaughterIndex = trackBuilder.template getDaughterIndex(negDaughter, trackProducts, mcCols, collisionBuilder, mcParticles, mcBuilder, mcProducts); fillCascade(collisionBuilder, cascadeProducts, cascade, col, bachelorIndex, posDaughterIndex, negDaughterIndex); if constexpr (modes::isEqual(cascadeType, modes::Cascade::kXi)) { - mcBuilder.template fillMcXiWithLabel(col, mcCols, cascade, mcParticles, mcProducts); + mcBuilder.template fillMcXiWithLabel(cascade, mcParticles, mcCols, mcProducts); } if constexpr (modes::isEqual(cascadeType, modes::Cascade::kOmega)) { - mcBuilder.template fillMcOmegaWithLabel(col, mcCols, cascade, mcParticles, mcProducts); + mcBuilder.template fillMcOmegaWithLabel(cascade, mcParticles, mcCols, mcProducts); } } } @@ -716,7 +716,8 @@ class CascadeBuilder } } - bool fillAnyTable() { return mFillAnyTable; } + [[nodiscard]] bool fillAnyTable() const { return mFillAnyTable; } + [[nodiscard]] bool isPassThrough() const { return mCascadeSelection.isPassThrough(); } private: CascadeSelection mCascadeSelection; diff --git a/PWGCF/Femto/Core/cascadeHistManager.h b/PWGCF/Femto/Core/cascadeHistManager.h index 663abe12f98..346716f138e 100644 --- a/PWGCF/Femto/Core/cascadeHistManager.h +++ b/PWGCF/Femto/Core/cascadeHistManager.h @@ -435,15 +435,15 @@ class CascadeHistManager } } - template - void fill(T1 const& cascadeCandidate, T2 const& tracks, T3 const& mcParticles, T4 const& mcMothers, T5 const& mcPartonicMothers) + template + void fill(T1 const& cascadeCandidate, T2 const& tracks, T3 const& col, T4 const& mcParticles, T5 const& mcMothers, T6 const& mcPartonicMothers) { auto posDaughter = tracks.rawIteratorAt(cascadeCandidate.posDauId() - tracks.offset()); - mPosDauManager.template fill(posDaughter, tracks, mcParticles, mcMothers, mcPartonicMothers); + mPosDauManager.template fill(posDaughter, tracks, col, mcParticles, mcMothers, mcPartonicMothers); auto negDaughter = tracks.rawIteratorAt(cascadeCandidate.negDauId() - tracks.offset()); - mNegDauManager.template fill(negDaughter, tracks, mcParticles, mcMothers, mcPartonicMothers); + mNegDauManager.template fill(negDaughter, tracks, col, mcParticles, mcMothers, mcPartonicMothers); auto bachelor = tracks.rawIteratorAt(cascadeCandidate.bachelorId() - tracks.offset()); - mBachelorManager.template fill(bachelor, tracks, mcParticles, mcMothers, mcPartonicMothers); + mBachelorManager.template fill(bachelor, tracks, col, mcParticles, mcMothers, mcPartonicMothers); if constexpr (modes::isFlagSet(mode, modes::Mode::kReco)) { this->fillAnalysis(cascadeCandidate); @@ -452,7 +452,7 @@ class CascadeHistManager this->fillQa(cascadeCandidate); } if constexpr (modes::isFlagSet(mode, modes::Mode::kMc)) { - this->template fillMc(cascadeCandidate, mcParticles, mcMothers, mcPartonicMothers); + this->template fillMc(cascadeCandidate, col, mcParticles, mcMothers, mcPartonicMothers); } } @@ -598,8 +598,8 @@ class CascadeHistManager } } - template - void fillMc(T1 const& cascadeCandidate, T2 const& /*mcParticles*/, T3 const& /*mcMothers*/, T4 const& /*mcPartonicMothers*/) + template + void fillMc(T1 const& cascadeCandidate, T2 const& col, T3 const& /*mcParticles*/, T4 const& /*mcMothers*/, T5 const& /*mcPartonicMothers*/) { // No MC Particle if (!cascadeCandidate.has_fMcParticle()) { @@ -614,17 +614,21 @@ class CascadeHistManager } // Retrieve MC particle - auto mcParticle = cascadeCandidate.template fMcParticle_as(); + auto mcParticle = cascadeCandidate.template fMcParticle_as(); + + // whether a particle is associated to a wrong collision or not cannot be known by the producer so we check it here + bool fromWrongCollision = mcParticle.fMcColId() != col.fMcColId(); - // missidentifed particles are special case // whether a particle is missidentfied or not cannot be known by the producer so we check it here bool isMissidentified = mcParticle.pdgCode() != mPdgCode; mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kTruePtVsPt, HistTable)), mcParticle.pt(), cascadeCandidate.pt()); mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kTrueEtaVsEta, HistTable)), mcParticle.eta(), cascadeCandidate.eta()); mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kTruePhiVsPhi, HistTable)), mcParticle.phi(), cascadeCandidate.phi()); - if (isMissidentified) { - mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), static_cast(modes::McOrigin::kMissidentified)); + if (fromWrongCollision) { + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), static_cast(modes::McOrigin::kFromWrongCollision)); + } else if (isMissidentified) { + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), static_cast(modes::McOrigin::kMissidentified)); } else { mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), mcParticle.origin()); } @@ -632,7 +636,7 @@ class CascadeHistManager // get mother if (mcParticle.has_fMcMother()) { - auto mother = mcParticle.template fMcMother_as(); + auto mother = mcParticle.template fMcMother_as(); mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kPdgMother, HistTable)), mother.pdgCode()); } else { mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kPdgMother, HistTable)), 0); @@ -640,7 +644,7 @@ class CascadeHistManager // get partonic mother if (mcParticle.has_fMcPartMoth()) { - auto partonicMother = mcParticle.template fMcPartMoth_as(); + auto partonicMother = mcParticle.template fMcPartMoth_as(); mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kPdgPartonicMother, HistTable)), partonicMother.pdgCode()); } else { mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kPdgPartonicMother, HistTable)), 0); @@ -648,8 +652,9 @@ class CascadeHistManager if constexpr (modes::isFlagSet(mode, modes::Mode::kQa)) { if (mPlotOrigins) { - // check first if particle is missidentified - if (isMissidentified) { + if (fromWrongCollision) { + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kFromWrongCollision, HistTable)), cascadeCandidate.pt(), cascadeCandidate.cascadeCosPa()); + } else if (isMissidentified) { // if it is, we fill it as such mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kMissidentified, HistTable)), cascadeCandidate.pt(), cascadeCandidate.cascadeCosPa()); } else { @@ -666,7 +671,7 @@ class CascadeHistManager break; case modes::McOrigin::kFromSecondaryDecay: if (mcParticle.has_fMcMother()) { - auto mother = mcParticle.template fMcMother_as(); + auto mother = mcParticle.template fMcMother_as(); int motherPdgCode = std::abs(mother.pdgCode()); // Switch on PDG of the mother if (mPlotNSecondaries >= histmanager::kSecondaryPlotLevel1 && motherPdgCode == mPdgCodesSecondaryMother[0]) { diff --git a/PWGCF/Femto/Core/charmHadronBuilder.h b/PWGCF/Femto/Core/charmHadronBuilder.h index 83b2121fcbf..3cacd3c4641 100644 --- a/PWGCF/Femto/Core/charmHadronBuilder.h +++ b/PWGCF/Femto/Core/charmHadronBuilder.h @@ -444,18 +444,21 @@ class CharmHadronBuilder auto prong0 = candidate.template prong0_as(); auto prong1 = candidate.template prong1_as(); - posDauIndex = trackBuilder.template getDaughterIndex(col, collisionBuilder, mcCols, prong0, trackProducts, mcParticles, mcBuilder, mcProducts); - negDauIndex = trackBuilder.template getDaughterIndex(col, collisionBuilder, mcCols, prong1, trackProducts, mcParticles, mcBuilder, mcProducts); + posDauIndex = trackBuilder.template getDaughterIndex(prong0, trackProducts, mcCols, collisionBuilder, mcParticles, mcBuilder, mcProducts); + negDauIndex = trackBuilder.template getDaughterIndex(prong1, trackProducts, mcCols, collisionBuilder, mcParticles, mcBuilder, mcProducts); if constexpr (modes::isEqual(hadronType, modes::CharmHadron::kD0)) { this->fillD0Tables(collisionProducts, d0Products, candidate, candidate.pt(), mHfHelper.invMassD0ToPiK(candidate), posDauIndex, negDauIndex); } else { this->fillD0Tables(collisionProducts, d0Products, candidate, -candidate.pt(), mHfHelper.invMassD0barToKPi(candidate), posDauIndex, negDauIndex); } - mcBuilder.template fillMcD0WithLabel(col, mcCols, candidate, tracks, mcParticles, mcProducts); + mcBuilder.template fillMcD0WithLabel(candidate, tracks, mcParticles, mcCols, mcProducts); } } + [[nodiscard]] bool fillAnyTable() const { return mFillAnyTable; } + [[nodiscard]] bool isPassThrough() const { return mD0Selection.isPassThrough(); } + private: D0Selection mD0Selection; HfHelper mHfHelper; diff --git a/PWGCF/Femto/Core/charmHadronHistManager.h b/PWGCF/Femto/Core/charmHadronHistManager.h index f17219d3bd7..86dc4fa965c 100644 --- a/PWGCF/Femto/Core/charmHadronHistManager.h +++ b/PWGCF/Femto/Core/charmHadronHistManager.h @@ -308,13 +308,13 @@ class CharmHadronHistManager } } - template - void fill(T1 const& charmHadronCandidate, T2 const& tracks, T3 const& mcParticles, T4 const& mcMothers, T5 const& mcPartonicMothers) + template + void fill(T1 const& charmHadronCandidate, T2 const& tracks, T3 const& col, T4 const& mcParticles, T5 const& mcMothers, T6 const& mcPartonicMothers) { auto prong0 = tracks.rawIteratorAt(charmHadronCandidate.posDauId() - tracks.offset()); - mProng0Manager.template fill(prong0, tracks, mcParticles, mcMothers, mcPartonicMothers); + mProng0Manager.template fill(prong0, tracks, col, mcParticles, mcMothers, mcPartonicMothers); auto prong1 = tracks.rawIteratorAt(charmHadronCandidate.negDauId() - tracks.offset()); - mProng1Manager.template fill(prong1, tracks, mcParticles, mcMothers, mcPartonicMothers); + mProng1Manager.template fill(prong1, tracks, col, mcParticles, mcMothers, mcPartonicMothers); if constexpr (modes::isFlagSet(mode, modes::Mode::kReco)) { this->fillAnalysis(charmHadronCandidate); diff --git a/PWGCF/Femto/Core/collisionBuilder.h b/PWGCF/Femto/Core/collisionBuilder.h index 7a4bce87173..3f6f94a1b32 100644 --- a/PWGCF/Femto/Core/collisionBuilder.h +++ b/PWGCF/Femto/Core/collisionBuilder.h @@ -694,7 +694,7 @@ class CollisionBuilder return; } this->template fillCollision(collisionProducts, col); - mcBuilder.template fillMcCollisionWithLabel(mcProducts, col, mcCols); + mcBuilder.template fillMcCollisionWithLabel(col, mcCols, mcProducts); } [[nodiscard]] int64_t collisionIndex() const { return mCurrentCollisionIndex; } @@ -704,6 +704,8 @@ class CollisionBuilder mCurrentCollisionIndex = -1; } + [[nodiscard]] bool fillAnyTable() const { return mFillAnyTable; } + [[nodiscard]] bool isPassThrough() const { return mCollisionSelection.isPassThrough(); } [[nodiscard]] bool producingCollisions() const { return mProducedCollisions; } [[nodiscard]] bool producingLiteCollisions() const { return mProducedLiteCollisions; } diff --git a/PWGCF/Femto/Core/kinkBuilder.h b/PWGCF/Femto/Core/kinkBuilder.h index ded1d92eba2..b90fa2248f9 100644 --- a/PWGCF/Femto/Core/kinkBuilder.h +++ b/PWGCF/Femto/Core/kinkBuilder.h @@ -619,15 +619,15 @@ class KinkBuilder collisionBuilder.template fillMcCollision(collisionProducts, col, mcCols, mcProducts, mcBuilder); auto daughter = kink.template trackDaug_as(); - daughterIndex = trackBuilder.template getDaughterIndex(col, collisionBuilder, mcCols, daughter, trackProducts, mcParticles, mcBuilder, mcProducts); + daughterIndex = trackBuilder.template getDaughterIndex(daughter, trackProducts, mcCols, collisionBuilder, mcParticles, mcBuilder, mcProducts); if constexpr (modes::isEqual(kinkType, modes::Kink::kSigma)) { fillSigma(collisionBuilder, kinkProducts, kink, daughterIndex); - mcBuilder.template fillMcSigmaWithLabel(col, mcCols, daughter, mcParticles, mcProducts); + mcBuilder.template fillMcSigmaWithLabel(daughter, mcParticles, mcCols, mcProducts); } if constexpr (modes::isEqual(kinkType, modes::Kink::kSigmaPlus)) { fillSigmaPlus(collisionBuilder, kinkProducts, kink, daughterIndex); - mcBuilder.template fillMcSigmaPlusWithLabel(col, mcCols, daughter, mcParticles, mcProducts); + mcBuilder.template fillMcSigmaPlusWithLabel(daughter, mcParticles, mcCols, mcProducts); } } } @@ -707,7 +707,8 @@ class KinkBuilder } } - bool fillAnyTable() { return mFillAnyTable; } + [[nodiscard]] bool fillAnyTable() const { return mFillAnyTable; } + [[nodiscard]] bool isPassThrough() const { return mKinkSelection.isPassThrough(); } private: KinkSelection mKinkSelection; diff --git a/PWGCF/Femto/Core/kinkHistManager.h b/PWGCF/Femto/Core/kinkHistManager.h index 1ffe73e272b..3e98b8865e0 100644 --- a/PWGCF/Femto/Core/kinkHistManager.h +++ b/PWGCF/Femto/Core/kinkHistManager.h @@ -386,11 +386,11 @@ class KinkHistManager } } - template - void fill(T1 const& kinkCandidate, T2 const& tracks, T3 const& mcParticles, T4 const& mcMothers, T5 const& mcPartonicMothers) + template + void fill(T1 const& kinkCandidate, T2 const& tracks, T3 const& col, T4 const& mcParticles, T5 const& mcMothers, T6 const& mcPartonicMothers) { auto chaDaughter = tracks.rawIteratorAt(kinkCandidate.chaDauId() - tracks.offset()); - mChaDauManager.template fill(chaDaughter, tracks, mcParticles, mcMothers, mcPartonicMothers); + mChaDauManager.template fill(chaDaughter, tracks, col, mcParticles, mcMothers, mcPartonicMothers); if constexpr (modes::isFlagSet(mode, modes::Mode::kReco)) { this->fillAnalysis(kinkCandidate); } @@ -398,7 +398,7 @@ class KinkHistManager this->fillQa(kinkCandidate); } if constexpr (modes::isFlagSet(mode, modes::Mode::kMc)) { - this->template fillMc(kinkCandidate, mcParticles, mcMothers, mcPartonicMothers); + this->template fillMc(kinkCandidate, col, mcParticles, mcMothers, mcPartonicMothers); } } @@ -530,8 +530,8 @@ class KinkHistManager } } - template - void fillMc(T1 const& kinkCandidate, T2 const& /*mcParticles*/, T3 const& /*mcMothers*/, T4 const& /*mcPartonicMothers*/) + template + void fillMc(T1 const& kinkCandidate, T2 const& col, T3 const& /*mcParticles*/, T4 const& /*mcMothers*/, T5 const& /*mcPartonicMothers*/) { // No MC Particle if (!kinkCandidate.has_fMcParticle()) { @@ -546,17 +546,21 @@ class KinkHistManager } // Retrieve MC particle - auto mcParticle = kinkCandidate.template fMcParticle_as(); + auto mcParticle = kinkCandidate.template fMcParticle_as(); + + // whether a particle is associated to a wrong collision or not cannot be known by the producer so we check it here + bool fromWrongCollision = mcParticle.fMcColId() != col.fMcColId(); - // missidentifed particles are special case // whether a particle is missidentfied or not cannot be known by the producer so we check it here bool isMissidentified = mcParticle.pdgCode() != mPdgCode; mHistogramRegistry->fill(HIST(kinkPrefix) + HIST(McDir) + HIST(getHistName(kTruePt, HistTable)), mcParticle.pt()); mHistogramRegistry->fill(HIST(kinkPrefix) + HIST(McDir) + HIST(getHistName(kTrueEta, HistTable)), mcParticle.eta()); mHistogramRegistry->fill(HIST(kinkPrefix) + HIST(McDir) + HIST(getHistName(kTruePhi, HistTable)), mcParticle.phi()); - if (isMissidentified) { - mHistogramRegistry->fill(HIST(kinkPrefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), static_cast(modes::McOrigin::kMissidentified)); + if (fromWrongCollision) { + mHistogramRegistry->fill(HIST(kinkPrefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), static_cast(modes::McOrigin::kFromWrongCollision)); + } else if (isMissidentified) { + mHistogramRegistry->fill(HIST(kinkPrefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), static_cast(modes::McOrigin::kMissidentified)); } else { mHistogramRegistry->fill(HIST(kinkPrefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), mcParticle.origin()); } @@ -564,7 +568,7 @@ class KinkHistManager // get mother if (mcParticle.has_fMcMother()) { - auto mother = mcParticle.template fMcMother_as(); + auto mother = mcParticle.template fMcMother_as(); mHistogramRegistry->fill(HIST(kinkPrefix) + HIST(McDir) + HIST(getHistName(kPdgMother, HistTable)), mother.pdgCode()); } else { mHistogramRegistry->fill(HIST(kinkPrefix) + HIST(McDir) + HIST(getHistName(kPdgMother, HistTable)), 0); @@ -572,7 +576,7 @@ class KinkHistManager // get partonic mother if (mcParticle.has_fMcPartMoth()) { - auto partonicMother = mcParticle.template fMcPartMoth_as(); + auto partonicMother = mcParticle.template fMcPartMoth_as(); mHistogramRegistry->fill(HIST(kinkPrefix) + HIST(McDir) + HIST(getHistName(kPdgPartonicMother, HistTable)), partonicMother.pdgCode()); } else { mHistogramRegistry->fill(HIST(kinkPrefix) + HIST(McDir) + HIST(getHistName(kPdgPartonicMother, HistTable)), 0); @@ -580,8 +584,9 @@ class KinkHistManager if constexpr (modes::isFlagSet(mode, modes::Mode::kQa)) { if (mPlotOrigins) { - // check first if particle is missidentified - if (isMissidentified) { + if (fromWrongCollision) { + mHistogramRegistry->fill(HIST(kinkPrefix) + HIST(McDir) + HIST(getHistName(kFromWrongCollision, HistTable)), kinkCandidate.pt(), kinkCandidate.kinkAngle()); + } else if (isMissidentified) { // if it is, we fill it as such mHistogramRegistry->fill(HIST(kinkPrefix) + HIST(McDir) + HIST(getHistName(kMissidentified, HistTable)), kinkCandidate.pt(), kinkCandidate.kinkAngle()); } else { @@ -598,7 +603,7 @@ class KinkHistManager break; case modes::McOrigin::kFromSecondaryDecay: if (mcParticle.has_fMcMother()) { - auto mother = mcParticle.template fMcMother_as(); + auto mother = mcParticle.template fMcMother_as(); int motherPdgCode = std::abs(mother.pdgCode()); // Switch on PDG of the mother if (mPlotNSecondaries >= histmanager::kSecondaryPlotLevel1 && motherPdgCode == mPdgCodesSecondaryMother[0]) { diff --git a/PWGCF/Femto/Core/mcBuilder.h b/PWGCF/Femto/Core/mcBuilder.h index 3fd1a86fdb7..488eeda4bb5 100644 --- a/PWGCF/Femto/Core/mcBuilder.h +++ b/PWGCF/Femto/Core/mcBuilder.h @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -41,13 +42,12 @@ namespace o2::analysis::femto::mcbuilder { -constexpr int ProducedByDecay = 4; - struct ConfMc : o2::framework::ConfigurableGroup { std::string prefix = std::string("MonteCarlo"); o2::framework::Configurable passThrough{"passThrough", false, "Passthrough all MC collisions and particles"}; o2::framework::Configurable findLastPartonicMother{"findLastPartonicMother", true, "If true, the partonic mother will be the first parton directly after the initial collision. If false, the partonic mother will be the last parton before hadronization"}; o2::framework::Configurable etaAcceptanceMcOnly{"etaAcceptanceMcOnly", 0.8, "For MC ONLY processing. |eta| acceptance for estimating primary track multiplicity"}; + o2::framework::Configurable etaAcceptanceMcReco{"etaAcceptanceMcReco", 1, "For MC/RECO processing. |eta| acceptance for generated particles"}; o2::framework::Configurable charmYGenMax{"charmYGenMax", 0.8f, "Max |y| (rapidity) for generated charm hadrons (mc-only truth acceptance)"}; }; @@ -131,6 +131,12 @@ class McBuilder { LOG(info) << "Initialize monte carlo builder..."; + mPassThrough = config.passThrough.value; + mEtaAcceptanceMcOnly = config.etaAcceptanceMcOnly.value; + mEtaAcceptanceMcReco = config.etaAcceptanceMcReco.value; + mFindLastPartonicMother = config.findLastPartonicMother.value; + mCharmYGenMax = config.charmYGenMax.value; + mProduceMcCollisions = utils::enableTable("FMcCols_001", table.produceMcCollisions.value, initContext); mProduceMcParticles = utils::enableTable("FMcParticles_001", table.produceMcParticles.value, initContext); mProduceMcMothers = utils::enableTable("FMcMothers_001", table.produceMcMothers.value, initContext); @@ -148,27 +154,24 @@ class McBuilder mProduceOmegaLabels = utils::enableTable("FOmegaLabels", table.producedOmegaLabels.value, initContext); if (mProduceMcCollisions || mProduceCollisionLabels || - mProduceMcParticles || mProduceMcMothers || mProduceMcPartonicMothers || - mProduceMcMotherLabels || + mProduceMcParticles || mProduceMcMotherLabels || + mProduceMcMothers || mProduceMcPartonicMothers || mProduceTrackLabels || mProduceLambdaLabels || mProduceK0shortLabels || mProduceSigmaLabels || mProduceSigmaPlusLabels || - mProduceXiLabels || mProduceOmegaLabels) { + mProduceXiLabels || mProduceOmegaLabels || + mProduceD0Labels) { mFillAnyTable = true; } else { LOG(info) << "No tables configured..."; LOG(info) << "Initialization done..."; return; } - mPassThrough = config.passThrough.value; - mEtaAcceptanceMcOnly = config.etaAcceptanceMcOnly.value; - mFindLastPartonicMother = config.findLastPartonicMother.value; - mCharmYGenMax = config.charmYGenMax.value; LOG(info) << "Initialization done..."; } template - void fillMcCollisionWithLabel(T1& mcProducts, T2 const& col, T3 const& /*mcCols*/) + void fillMcCollisionWithLabel(T1 const& col, T2 const& /*mcCols*/, T3& mcProducts) { if (!mProduceCollisionLabels) { mcProducts.producedCollisionLabels(-1); @@ -181,7 +184,7 @@ class McBuilder auto it = mCollisionMap.find(originalIndex); if (it == mCollisionMap.end()) { // Not yet created → create it - auto mcCol = col.template mcCollision_as(); + auto mcCol = col.template mcCollision_as(); this->fillMcCollision(mcCol, mcProducts); } // Add label @@ -195,6 +198,10 @@ class McBuilder template void fillMcCollision(T1 const& mcCol, T2& mcProducts) { + // check if collision already exists + if (mCollisionMap.find(mcCol.globalIndex()) != mCollisionMap.end()) { + return; + } float centrality = -1; float multiplicity = -1; if constexpr (modes::isFlagSet(system, modes::System::kPP)) { @@ -214,18 +221,28 @@ class McBuilder } // for mc only - template - void fillMcCollision(T1 const& mcCol, T2 const& mcParticles, T3& mcProducts) + template + void fillMcCollision(T1 const& mcCol, T2 const& mcParticles, T3& mcProducts, T4& pdgDb) { + // check if collision already exists + if (mCollisionMap.find(mcCol.globalIndex()) != mCollisionMap.end()) { + return; + } + float centrality = 0; // no centrality estimator for mc only, so set to 0 float multiplicity = 0; // no multiplicity estimator for mc only - // define multiplicity ourselves by counting primary particles for |eta|,0.8 + // define multiplicity ourselves by counting primary particles for |eta|< some config threshold // this is similar to how define it in data for (auto const& mcParticle : mcParticles) { - if (mcParticle.isPhysicalPrimary() && (std::fabs(mcParticle.eta()) < mEtaAcceptanceMcOnly)) { - multiplicity += 1; + if (!mcParticle.isPhysicalPrimary() || std::fabs(mcParticle.eta()) > mEtaAcceptanceMcOnly) { + continue; + } + const auto* pdgParticle = pdgDb->GetParticle(mcParticle.pdgCode()); + if (pdgParticle == nullptr || std::fabs(pdgParticle->Charge()) < o2::constants::math::Almost0) { + continue; } + multiplicity += 1; } mcProducts.producedMcCollisions( @@ -254,50 +271,76 @@ class McBuilder this->getOrCreateMcParticleRow(mcParticle, mcParticles, mcCol, mcProducts); } + /// Write the generated primary charged particles needed for the dNch/deta calculation template - void fillMcTrackWithLabel(T1 const& col, T2 const& mcCols, T3 const& track, T4 const& mcParticles, T5& mcProducts) + void fillMcPassThrough(T1 const& mcCols, T2 const& mcParticles, T3& perMcCollision, T4& mcProducts, T5& pdgDb) + { + if (!mPassThrough) { + return; + } + for (const auto& mcCol : mcCols) { + // every MC collision unconditionally: E_all is counted over all of them + this->fillMcCollision(mcCol, mcProducts); + + auto particlesThisCollision = mcParticles.sliceBy(perMcCollision, mcCol.globalIndex()); + for (const auto& mcParticle : particlesThisCollision) { + if (!mcParticle.isPhysicalPrimary() || std::fabs(mcParticle.eta()) > mEtaAcceptanceMcReco) { + continue; + } + const auto* pdgParticle = pdgDb->GetParticle(mcParticle.pdgCode()); + if (pdgParticle == nullptr || std::fabs(pdgParticle->Charge()) < o2::constants::math::Almost0) { + continue; + } + // NOTE: full mcParticles table, never the slice - the ancestry walk resolves global indices + this->fillMcParticle(mcParticle, mcParticles, mcCol, mcProducts); + } + } + } + + template + void fillMcTrackWithLabel(T1 const& track, T2 const& mcParticles, T3 const& mcCols, T4& mcProducts) { if (!mProduceTrackLabels) { mcProducts.producedTrackLabels(-1); return; } - fillMcLabelGeneric(col, mcCols, track, mcParticles, mcProducts, [](auto& prod, int64_t p) { prod.producedTrackLabels(p); }); + fillMcLabelGeneric(track, mcParticles, mcCols, mcProducts, [](auto& prod, int64_t p) { prod.producedTrackLabels(p); }); } - template - void fillMcLambdaWithLabel(T1 const& col, T2 const& mcCols, T3 const& lambda, T4 const& mcParticles, T5& mcProducts) + template + void fillMcLambdaWithLabel(T1 const& lambda, T2 const& mcParticles, T3 const& mcCols, T4& mcProducts) { if (!mProduceLambdaLabels) { mcProducts.producedLambdaLabels(-1); return; } - fillMcLabelGeneric(col, mcCols, lambda, mcParticles, mcProducts, [](auto& prod, int64_t p) { prod.producedLambdaLabels(p); }); + fillMcLabelGeneric(lambda, mcParticles, mcCols, mcProducts, [](auto& prod, int64_t p) { prod.producedLambdaLabels(p); }); } - template - void fillMcK0shortWithLabel(T1 const& col, T2 const& mcCols, T3 const& k0short, T4 const& mcParticles, T5& mcProducts) + template + void fillMcK0shortWithLabel(T1 const& k0short, T2 const& mcParticles, T3 const& mcCols, T4& mcProducts) { if (!mProduceK0shortLabels) { mcProducts.producedK0shortLabels(-1); return; } - fillMcLabelGeneric(col, mcCols, k0short, mcParticles, mcProducts, [](auto& prod, int64_t p) { prod.producedK0shortLabels(p); }); + fillMcLabelGeneric(k0short, mcParticles, mcCols, mcProducts, [](auto& prod, int64_t p) { prod.producedK0shortLabels(p); }); } // D0 has no direct MC label (2-prong hypothesis built by PWGHF), so fillMcLabelGeneric // cannot be reused. Both prongs are matched to a generated D0 -> K pi decay with // RecoDecay::getMatchedMCRec, which returns the index of the generated mother; // unmatched candidates get -1. - template - void fillMcD0WithLabel(T1 const& /*col*/, T2 const& /*mcCols*/, T3 const& d0candidate, T4 const& /*tracks*/, T5 const& mcParticles, T6& mcProducts) + template + void fillMcD0WithLabel(T1 const& d0candidate, T2 const& /*tracks*/, T3 const& mcParticles, T4 const& /*mcCols*/, T5& mcProducts) { if (!mProduceD0Labels) { mcProducts.producedD0Labels(-1); return; } - auto prong0 = d0candidate.template prong0_as(); - auto prong1 = d0candidate.template prong1_as(); + auto prong0 = d0candidate.template prong0_as(); + auto prong1 = d0candidate.template prong1_as(); auto arrayDaughters = std::array{prong0, prong1}; int8_t sign = 0; const int indexMcRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, o2::constants::physics::Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign); @@ -308,53 +351,54 @@ class McBuilder } auto mcParticle = mcParticles.rawIteratorAt(indexMcRec); - auto mcCol = mcParticle.template mcCollision_as(); + auto mcCol = mcParticle.template mcCollision_as(); int64_t mcParticleRow = this->getOrCreateMcParticleRow(mcParticle, mcParticles, mcCol, mcProducts); mcProducts.producedD0Labels(mcParticleRow); } - template - void fillMcSigmaWithLabel(T1 const& col, T2 const& mcCols, T3 const& sigmaDaughter, T4 const& mcParticles, T5& mcProducts) + template + void fillMcSigmaWithLabel(T1 const& sigmaDaughter, T2 const& mcParticles, T3 const& mcCols, T4& mcProducts) { if (!mProduceSigmaLabels) { mcProducts.producedSigmaLabels(-1); return; } - fillMcLabelGeneric(col, mcCols, sigmaDaughter, mcParticles, mcProducts, [](auto& prod, int64_t p) { prod.producedSigmaLabels(p); }, true); + fillMcLabelGeneric(sigmaDaughter, mcParticles, mcCols, mcProducts, [](auto& prod, int64_t p) { prod.producedSigmaLabels(p); }, true); } - template - void fillMcSigmaPlusWithLabel(T1 const& col, T2 const& mcCols, T3 const& sigmaPlusDaughter, T4 const& mcParticles, T5& mcProducts) + template + void fillMcSigmaPlusWithLabel(T1 const& sigmaPlusDaughter, T2 const& mcParticles, T3 const& mcCols, T4& mcProducts) { if (!mProduceSigmaPlusLabels) { mcProducts.producedSigmaPlusLabels(-1); return; } - fillMcLabelGeneric(col, mcCols, sigmaPlusDaughter, mcParticles, mcProducts, [](auto& prod, int64_t p) { prod.producedSigmaPlusLabels(p); }, true); + fillMcLabelGeneric(sigmaPlusDaughter, mcParticles, mcCols, mcProducts, [](auto& prod, int64_t p) { prod.producedSigmaPlusLabels(p); }, true); } - template - void fillMcXiWithLabel(T1 const& col, T2 const& mcCols, T3 const& xi, T4 const& mcParticles, T5& mcProducts) + template + void fillMcXiWithLabel(T1 const& xi, T2 const& mcParticles, T3 const& mcCols, T4& mcProducts) { if (!mProduceXiLabels) { mcProducts.producedXiLabels(-1); return; } - fillMcLabelGeneric(col, mcCols, xi, mcParticles, mcProducts, [](auto& prod, int64_t p) { prod.producedXiLabels(p); }); + fillMcLabelGeneric(xi, mcParticles, mcCols, mcProducts, [](auto& prod, int64_t p) { prod.producedXiLabels(p); }); } - template - void fillMcOmegaWithLabel(T1 const& col, T2 const& mcCols, T3 const& omega, T4 const& mcParticles, T5& mcProducts) + template + void fillMcOmegaWithLabel(T1 const& omega, T2 const& mcParticles, T3 const& mcCols, T4& mcProducts) { if (!mProduceOmegaLabels) { mcProducts.producedOmegaLabels(-1); return; } - fillMcLabelGeneric(col, mcCols, omega, mcParticles, mcProducts, [](auto& prod, int64_t p) { prod.producedOmegaLabels(p); }); + fillMcLabelGeneric(omega, mcParticles, mcCols, mcProducts, [](auto& prod, int64_t p) { prod.producedOmegaLabels(p); }); } bool fillAnyTable() const { return mFillAnyTable; } + bool isPassThrough() const { return mPassThrough; } template void reset(T1 const& mcCollisions, T2 const& mcParticles) @@ -369,19 +413,6 @@ class McBuilder mMcPartonicMotherMap.reserve(mcParticles.size()); } - // mc only, then there is only 1 mc collision - template - void reset(T const& mcParticles) - { - mCollisionMap.clear(); - mMcParticleMap.clear(); - mMcParticleMap.reserve(mcParticles.size()); - mMcMotherMap.clear(); - mMcMotherMap.reserve(mcParticles.size()); - mMcPartonicMotherMap.clear(); - mMcPartonicMotherMap.reserve(mcParticles.size()); - } - private: // classify a charm hadron as prompt (charm from a c quark) or non-prompt (charm from a // beauty decay) from the mc decay tree; shared by the reco-matched and generator-level paths @@ -392,42 +423,30 @@ class McBuilder return (charmOrigin == RecoDecay::OriginType::NonPrompt) ? modes::McOrigin::kNonPrompt : modes::McOrigin::kPrompt; } - template - modes::McOrigin getOrigin(T1 const& col, T2 const& /*mcCols*/, T3 const& mcParticle) + template + modes::McOrigin getOrigin(T1 const& mcParticle) { // whether a particle is misidentified or not can only be checked by qa/pair task later so it is not set here - - // check if reconstructed collision has a generated collision - if (!col.has_mcCollision()) { - return modes::McOrigin::kFromWrongCollision; - } - - // now check collision ids, if they do not match, then the track belongs to another collision - if (col.mcCollisionId() != mcParticle.mcCollisionId()) { - return modes::McOrigin::kFromWrongCollision; - } - + // whether a particle is associated to the wrong collision or not can only be checked by qa/pair task later so it is not set here if (mcParticle.isPhysicalPrimary()) { return modes::McOrigin::kPhysicalPrimary; } - if (mcParticle.has_mothers() && mcParticle.getProcess() == ProducedByDecay) { + // A non-primary the generator itself produced can only come from a decay the generator + // performed, and strong/EM decay products are primaries by definition - so this is a + // weak decay. NOTE: getProcess() returns kPrimary (0) for every generator particle, + // so the kPDecay check below never fires for them. + if (mcParticle.producedByGenerator()) { return modes::McOrigin::kFromSecondaryDecay; } - - // not a primary and not from a decay and not from a wrong collision, we label as material - return modes::McOrigin::kFromMaterial; - } - - template - modes::McOrigin getOrigin(T1 const& mcParticle) - { - if (mcParticle.isPhysicalPrimary()) { - return modes::McOrigin::kPhysicalPrimary; - } - if (mcParticle.has_mothers() && mcParticle.getProcess() == ProducedByDecay) { + // produced by transport: kPDecay means GEANT decayed it, the usual path for + // Lambda / K0s / Xi / Omega since ALICE hands them to transport undecayed + const int process = mcParticle.getProcess(); + if (process == TMCProcess::kPDecay || process == TMCProcess::kPRadDecay) { return modes::McOrigin::kFromSecondaryDecay; } + + // not a primary and not from a decay we label as material return modes::McOrigin::kFromMaterial; } @@ -445,8 +464,6 @@ class McBuilder return it->second; } - /// Mc-only entry point: no reconstructed collision to match against, so origin - /// is derived purely from the mc particle itself. template int64_t getOrCreateMcParticleRow(T1 const& mcParticle, T2 const& mcParticles, T3 const& mcCol, T4& mcProducts) { @@ -456,17 +473,6 @@ class McBuilder return this->buildMcParticleRow(mcParticle, mcParticles, mcCol, origin, mcProducts); } - /// Reco-matched entry point: origin is derived by comparing the reconstructed - /// collision against the mc collision. - template - int64_t getOrCreateMcParticleRow(T1 const& col, T2 const& mcCols, T3 const& mcParticle, T4 const& mcParticles, T5 const& mcCol, T6& mcProducts) - { - auto origin = std::abs(mcParticle.pdgCode()) == o2::constants::physics::Pdg::kD0 - ? this->getHeavyFlavourOrigin(mcParticle, mcParticles) - : this->getOrigin(col, mcCols, mcParticle); - return this->buildMcParticleRow(mcParticle, mcParticles, mcCol, origin, mcProducts); - } - /// Find-or-create the FMcParticles row for mcParticle. On first creation, also /// resolves the mother / partonic mother (with kinematics) and writes the single /// corresponding FMcMotherLabels row, so it always stays in lockstep, one row @@ -496,7 +502,7 @@ class McBuilder // --- mother --- int64_t mcMotherRow = -1; - if (mcParticle.has_mothers()) { + if (mProduceMcMothers && mcParticle.has_mothers()) { auto mothers = mcParticle.template mothers_as(); auto motherParticle = mothers.front(); auto mcMotherIndex = motherParticle.globalIndex(); @@ -519,9 +525,12 @@ class McBuilder // --- partonic mother --- int64_t mcPartonicMotherRow = -1; - int64_t mcPartonicMotherIndex = mFindLastPartonicMother - ? this->findLastPartonicMother(mcParticle, mcParticles) - : this->findFirstPartonicMother(mcParticle, mcParticles); + int64_t mcPartonicMotherIndex = -1; + if (mProduceMcPartonicMothers) { + mcPartonicMotherIndex = mFindLastPartonicMother + ? this->findLastPartonicMother(mcParticle, mcParticles) + : this->findFirstPartonicMother(mcParticle, mcParticles); + } if (mcPartonicMotherIndex >= 0) { auto itPM = mMcPartonicMotherMap.find(mcPartonicMotherIndex); if (itPM != mMcPartonicMotherMap.end()) { @@ -542,13 +551,12 @@ class McBuilder return mcParticleRow; } - template - void fillMcLabelGeneric(T1 const& col, - T2 const& mcCols, - T3 const& particle, - T4 const& mcParticles, - T5& mcProducts, - T6 writeLabels, + template + void fillMcLabelGeneric(T1 const& particle, + T2 const& mcParticles, + T3 const& /*mcCols*/, + T4& mcProducts, + T5 writeLabels, bool startFromMotherParticle = false) { if (!particle.has_mcParticle()) { @@ -556,21 +564,21 @@ class McBuilder return; } - auto mcParticle = particle.template mcParticle_as(); - auto mcCol = mcParticle.template mcCollision_as(); + auto mcParticle = particle.template mcParticle_as(); + auto mcCol = mcParticle.template mcCollision_as(); if (startFromMotherParticle) { // in case of e.g. sigmas we do not reconstruct the mother but the daughter, so here we want to start from the mother particle - auto mcDaughterParticle = particle.template mcParticle_as(); + auto mcDaughterParticle = particle.template mcParticle_as(); if (!mcDaughterParticle.has_mothers()) { writeLabels(mcProducts, -1); return; } - auto mothersOfDaughter = mcDaughterParticle.template mothers_as(); + auto mothersOfDaughter = mcDaughterParticle.template mothers_as(); mcParticle = mothersOfDaughter.front(); } - int64_t mcParticleRow = this->getOrCreateMcParticleRow(col, mcCols, mcParticle, mcParticles, mcCol, mcProducts); + int64_t mcParticleRow = this->getOrCreateMcParticleRow(mcParticle, mcParticles, mcCol, mcProducts); writeLabels(mcProducts, mcParticleRow); } @@ -662,7 +670,7 @@ class McBuilder } currentIndex = nextIndex; } - return -1; + return lastPartonIndex; } bool mPassThrough = false; @@ -683,9 +691,10 @@ class McBuilder bool mProduceXiLabels = false; bool mProduceOmegaLabels = false; bool mProduceMcMotherLabels = false; - float mCharmYGenMax = 0.8; + float mCharmYGenMax = 0.8f; - float mEtaAcceptanceMcOnly = 0.8; + float mEtaAcceptanceMcOnly = 0.8f; + float mEtaAcceptanceMcReco = 1.f; std::unordered_map mCollisionMap; diff --git a/PWGCF/Femto/Core/modes.h b/PWGCF/Femto/Core/modes.h index c928e31b1d5..fdcab607c38 100644 --- a/PWGCF/Femto/Core/modes.h +++ b/PWGCF/Femto/Core/modes.h @@ -101,12 +101,12 @@ enum class Particle : o2::analysis::femto::datatypes::ParticleType { }; enum class McOrigin : o2::analysis::femto::datatypes::McOriginType { - kNoMcParticle = 0, // no associated mc particle normally indicated a wrongly reconstruced partilce - kFromWrongCollision = 1, // partilce originates from the wrong collision or a collision which was wrongly reconstructed (like a split vertex) + kNoMcParticle = 0, // no associated mc particle, normally indicated by wrongly reconstructed particle + kFromWrongCollision = 1, // particle originates from the wrong collision or a collision which was wrongly reconstructed (like a split vertex) kPhysicalPrimary = 2, // primary particle kFromSecondaryDecay = 3, // particle from secondary decay - kFromMaterial = 4, // partilce orginates from material - kMissidentified = 5, // partilce was kMissidentified (also know as fake) + kFromMaterial = 4, // particle originates from material + kMissidentified = 5, // particle was kMissidentified (also know as fake) kPrompt = 6, // HF only: charm hadron produced promptly (from c quark) kNonPrompt = 7, // HF only: charm hadron from beauty decay kMcOriginLast = 8 diff --git a/PWGCF/Femto/Core/pairProcessHelpers.h b/PWGCF/Femto/Core/pairProcessHelpers.h index b4d05f37be5..9606051ff57 100644 --- a/PWGCF/Femto/Core/pairProcessHelpers.h +++ b/PWGCF/Femto/Core/pairProcessHelpers.h @@ -119,7 +119,7 @@ void processSameEvent(T1 const& SliceParticle, if (!ParticleCleaner.isClean(part, mcParticles, mcMothers, mcPartonicMothers)) { continue; } - ParticleHistManager.template fill(part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); + ParticleHistManager.template fill(part, TrackTable, Collision, mcParticles, mcMothers, mcPartonicMothers); } for (auto const& [p1, p2] : o2::soa::combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(SliceParticle, SliceParticle))) { // check if particles are clean @@ -246,13 +246,13 @@ void processSameEvent(T1 const& SliceParticle1, if (!ParticleCleaner1.isClean(part, mcParticles, mcMothers, mcPartonicMothers)) { continue; } - ParticleHistManager1.template fill(part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); + ParticleHistManager1.template fill(part, TrackTable, Collision, mcParticles, mcMothers, mcPartonicMothers); } for (auto const& part : SliceParticle2) { if (!ParticleCleaner2.isClean(part, mcParticles, mcMothers, mcPartonicMothers)) { continue; } - ParticleHistManager2.template fill(part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); + ParticleHistManager2.template fill(part, TrackTable, Collision, mcParticles, mcMothers, mcPartonicMothers); } for (auto const& [p1, p2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(SliceParticle1, SliceParticle2))) { // check if particles are clean diff --git a/PWGCF/Femto/Core/trackBuilder.h b/PWGCF/Femto/Core/trackBuilder.h index a095b925212..c7a6f711faf 100644 --- a/PWGCF/Femto/Core/trackBuilder.h +++ b/PWGCF/Femto/Core/trackBuilder.h @@ -755,18 +755,18 @@ class TrackBuilder collisionBuilder.template fillMcCollision(collisionProducts, col, mcCols, mcProducts, mcBuilder); // get track from the track table so we can dereference mc particle properly auto track = tracks.iteratorAt(trackWithItsPid.index()); - this->template fillMcTrack(col, collisionBuilder, mcCols, track, trackWithItsPid, trackProducts, mcParticles, mcBuilder, mcProducts); + this->template fillMcTrack(track, trackWithItsPid, trackProducts, mcCols, collisionBuilder, mcParticles, mcBuilder, mcProducts); } } - template - bool fillMcTrack(T1 const& col, T2& collisionBuilder, T3 const& mcCols, T4 const& track, T5 const& trackWithItsPid, T6& trackProducts, T7 const& mcParticles, T8& mcBuilder, T9& mcProducts) + template + bool fillMcTrack(T1 const& track, T2 const& trackWithItsPid, T3& trackProducts, T4 const& mcCols, T5& collisionBuilder, T6 const& mcParticles, T7& mcBuilder, T8& mcProducts) { if (!mProduceTracks && !mProduceLiteTracks) { return false; } this->template fillTrack(trackWithItsPid, trackProducts, collisionBuilder); - mcBuilder.template fillMcTrackWithLabel(col, mcCols, track, mcParticles, mcProducts); + mcBuilder.template fillMcTrackWithLabel(track, mcParticles, mcCols, mcProducts); return true; } @@ -785,15 +785,15 @@ class TrackBuilder return indexMap.at(daughter.globalIndex()); } - template - int64_t getDaughterIndex(const T1& col, T2& collisionBuilder, T3 const& mcCols, const T4& daughter, T5& trackProducts, T6 const& mcParticles, T7& mcBuilder, T8& mcProducts) + template + int64_t getDaughterIndex(const T1& daughter, T2& trackProducts, T3 const& mcCols, T4& collisionBuilder, T5 const& mcParticles, T6& mcBuilder, T7& mcProducts) { auto result = utils::getIndex(daughter.globalIndex(), indexMap); if (result) { // daugher already in track table return result.value(); } - if (!this->template fillMcTrack(col, collisionBuilder, mcCols, daughter, daughter, trackProducts, mcParticles, mcBuilder, mcProducts)) { + if (!this->template fillMcTrack(daughter, daughter, trackProducts, mcCols, collisionBuilder, mcParticles, mcBuilder, mcProducts)) { LOG(fatal) << "Trying to register a daughter track, but FTracks or FLiteTrack table is disabled. " << "Enable TrackTables.produceTracks/produceLiteTracks when V0/Cascade/Kink tables that need daughter indices are enabled."; } @@ -801,6 +801,8 @@ class TrackBuilder return indexMap.at(daughter.globalIndex()); } + [[nodiscard]] bool fillAnyTable() const { return mFillAnyTable; } + [[nodiscard]] bool isPassThrough() const { return mTrackSelection.isPassThrough(); } [[nodiscard]] bool producingTracks() const { return mProduceTracks; } [[nodiscard]] bool producingLiteTracks() const { return mProduceLiteTracks; } diff --git a/PWGCF/Femto/Core/trackHistManager.h b/PWGCF/Femto/Core/trackHistManager.h index aeaa75d4418..058f13af0cb 100644 --- a/PWGCF/Femto/Core/trackHistManager.h +++ b/PWGCF/Femto/Core/trackHistManager.h @@ -640,8 +640,8 @@ class TrackHistManager } } - template - void fill(T1 const& track, T2 const& /*trackTable*/, T3 const& mcParticles, T4 const& mcMothers, T5 const& mcPartonicMothers) + template + void fill(T1 const& track, T2 const& /*trackTable*/, T3 const& col, T4 const& mcParticles, T5 const& mcMothers, T6 const& mcPartonicMothers) { if constexpr (isFlagSet(mode, modes::Mode::kReco)) { this->fillAnalysis(track); @@ -650,7 +650,7 @@ class TrackHistManager this->fillQa(track); } if constexpr (isFlagSet(mode, modes::Mode::kMc)) { - this->template fillMc(track, mcParticles, mcMothers, mcPartonicMothers); + this->template fillMc(track, col, mcParticles, mcMothers, mcPartonicMothers); } } @@ -958,8 +958,8 @@ class TrackHistManager } } - template - void fillMc(T1 const& track, T2 const& /*mcParticles*/, T3 const& /*mcMothers*/, T4 const& /*mcPartonicMothers*/) + template + void fillMc(T1 const& track, T2 const& col, T3 const& /*mcParticles*/, T4 const& /*mcMothers*/, T5 const& /*mcPartonicMothers*/) { // No MC Particle if (!track.has_fMcParticle()) { @@ -974,7 +974,11 @@ class TrackHistManager } // Retrieve MC particle - auto mcParticle = track.template fMcParticle_as(); + auto mcParticle = track.template fMcParticle_as(); + + // particles associcated to wrong collision + // whether a particle is associated to a wrong collision or not cannot be known by the producer so we check it here + bool fromWrongCollision = mcParticle.fMcColId() != col.fMcColId(); // missidentifed particles are special case // whether a particle is missidentfied or not cannot be known by the producer so we check it here @@ -983,8 +987,10 @@ class TrackHistManager mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kTruePtVsPt, HistTable)), mcParticle.pt(), track.pt()); mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kTrueEtaVsEta, HistTable)), mcParticle.eta(), track.eta()); mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kTruePhiVsPhi, HistTable)), mcParticle.phi(), track.phi()); - if (isMissidentified) { - mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), static_cast(modes::McOrigin::kMissidentified)); + if (fromWrongCollision) { + mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), static_cast(modes::McOrigin::kFromWrongCollision)); + } else if (isMissidentified) { + mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), static_cast(modes::McOrigin::kMissidentified)); } else { mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), mcParticle.origin()); } @@ -992,7 +998,7 @@ class TrackHistManager // get mother if (mcParticle.has_fMcMother()) { - auto mother = mcParticle.template fMcMother_as(); + auto mother = mcParticle.template fMcMother_as(); mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kPdgMother, HistTable)), mother.pdgCode()); } else { mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kPdgMother, HistTable)), 0); @@ -1000,7 +1006,7 @@ class TrackHistManager // get partonic mother if (mcParticle.has_fMcPartMoth()) { - auto partonicMother = mcParticle.template fMcPartMoth_as(); + auto partonicMother = mcParticle.template fMcPartMoth_as(); mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kPdgPartonicMother, HistTable)), partonicMother.pdgCode()); } else { mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kPdgPartonicMother, HistTable)), 0); @@ -1008,8 +1014,10 @@ class TrackHistManager if constexpr (modes::isFlagSet(mode, modes::Mode::kQa)) { if (mPlotOrigins) { - // check first if particle is missidentified - if (isMissidentified) { + // check first if particle is from a wrong collision + if (fromWrongCollision) { + mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kFromWrongCollision, HistTable)), track.pt(), track.dcaXY(), track.dcaZ()); + } else if (isMissidentified) { // if it is, we fill it as such mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kMissidentified, HistTable)), track.pt(), track.dcaXY(), track.dcaZ()); } else { @@ -1018,15 +1026,12 @@ class TrackHistManager case modes::McOrigin::kPhysicalPrimary: mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kPrimary, HistTable)), track.pt(), track.dcaXY(), track.dcaZ()); break; - case modes::McOrigin::kFromWrongCollision: - mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kFromWrongCollision, HistTable)), track.pt(), track.dcaXY(), track.dcaZ()); - break; case modes::McOrigin::kFromMaterial: mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kFromMaterial, HistTable)), track.pt(), track.dcaXY(), track.dcaZ()); break; case modes::McOrigin::kFromSecondaryDecay: if (mcParticle.has_fMcMother()) { - auto mother = mcParticle.template fMcMother_as(); + auto mother = mcParticle.template fMcMother_as(); int motherPdgCode = std::abs(mother.pdgCode()); // Switch on PDG of the mother if (mPlotNSecondaries >= histmanager::kSecondaryPlotLevel1 && motherPdgCode == mPdgCodesSecondaryMother[0]) { diff --git a/PWGCF/Femto/Core/tripletProcessHelpers.h b/PWGCF/Femto/Core/tripletProcessHelpers.h index 1bfbfad796b..932f91b37c4 100644 --- a/PWGCF/Femto/Core/tripletProcessHelpers.h +++ b/PWGCF/Femto/Core/tripletProcessHelpers.h @@ -35,7 +35,6 @@ enum TripletOrder : uint8_t { }; // process same event for identical 3 particles -// (no cleaner here — ParticleCleaner only operates on MC info, see the mc overload below) template @@ -170,7 +168,6 @@ void processSameEvent(T1 const& SliceParticle1, // 1&2 have same species } // process same event for 3 different particles -// (no cleaner here — ParticleCleaner only operates on MC info, see the mc overload below) template (part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); + ParticleHistManager.template fill(part, TrackTable, Collision, mcParticles, mcMothers, mcPartonicMothers); } for (auto const& [p1, p2, p3] : o2::soa::combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(SliceParticle, SliceParticle, SliceParticle))) { @@ -320,7 +316,6 @@ void processSameEvent(T1 const& SliceParticle, } // process same event for 2 identical particles and one other with mc information -// NOTE: added `Cleaner1` (for particle 1&2) and `Cleaner3` (for particle 3, a different species) template @@ -347,13 +342,13 @@ void processSameEvent(T1 const& SliceParticle1, if (!Cleaner1.isClean(part, mcParticles, mcMothers, mcPartonicMothers)) { continue; } - ParticleHistManager1.template fill(part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); + ParticleHistManager1.template fill(part, TrackTable, Collision, mcParticles, mcMothers, mcPartonicMothers); } for (auto const& part : SliceParticle3) { if (!Cleaner3.isClean(part, mcParticles, mcMothers, mcPartonicMothers)) { continue; } - ParticleHistManager3.template fill(part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); + ParticleHistManager3.template fill(part, TrackTable, Collision, mcParticles, mcMothers, mcPartonicMothers); } for (auto const& p3 : SliceParticle3) { @@ -443,19 +438,19 @@ void processSameEvent(T1 const& SliceParticle1, if (!Cleaner1.isClean(part, mcParticles, mcMothers, mcPartonicMothers)) { continue; } - ParticleHistManager1.template fill(part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); + ParticleHistManager1.template fill(part, TrackTable, Collision, mcParticles, mcMothers, mcPartonicMothers); } for (auto const& part : SliceParticle2) { if (!Cleaner2.isClean(part, mcParticles, mcMothers, mcPartonicMothers)) { continue; } - ParticleHistManager2.template fill(part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); + ParticleHistManager2.template fill(part, TrackTable, Collision, mcParticles, mcMothers, mcPartonicMothers); } for (auto const& part : SliceParticle3) { if (!Cleaner3.isClean(part, mcParticles, mcMothers, mcPartonicMothers)) { continue; } - ParticleHistManager3.template fill(part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); + ParticleHistManager3.template fill(part, TrackTable, Collision, mcParticles, mcMothers, mcPartonicMothers); } for (auto const& [p1, p2, p3] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(SliceParticle1, SliceParticle2, SliceParticle3))) { diff --git a/PWGCF/Femto/Core/v0Builder.h b/PWGCF/Femto/Core/v0Builder.h index 1956df08357..9078ae4b993 100644 --- a/PWGCF/Femto/Core/v0Builder.h +++ b/PWGCF/Femto/Core/v0Builder.h @@ -609,22 +609,22 @@ class V0Builder collisionBuilder.template fillMcCollision(collisionProducts, col, mcCols, mcProducts, mcBuilder); auto posDaughter = v0.template posTrack_as(); - posDaughterIndex = trackBuilder.template getDaughterIndex(col, collisionBuilder, mcCols, posDaughter, trackProducts, mcParticles, mcBuilder, mcProducts); + posDaughterIndex = trackBuilder.template getDaughterIndex(posDaughter, trackProducts, mcCols, collisionBuilder, mcParticles, mcBuilder, mcProducts); auto negDaughter = v0.template negTrack_as(); - negDaughterIndex = trackBuilder.template getDaughterIndex(col, collisionBuilder, mcCols, negDaughter, trackProducts, mcParticles, mcBuilder, mcProducts); + negDaughterIndex = trackBuilder.template getDaughterIndex(negDaughter, trackProducts, mcCols, collisionBuilder, mcParticles, mcBuilder, mcProducts); if constexpr (modes::isEqual(v0Type, modes::V0::kLambda)) { fillLambda(collisionBuilder, v0Products, v0, 1.f, posDaughterIndex, negDaughterIndex); - mcBuilder.template fillMcLambdaWithLabel(col, mcCols, v0, mcParticles, mcProducts); + mcBuilder.template fillMcLambdaWithLabel(v0, mcParticles, mcCols, mcProducts); } if constexpr (modes::isEqual(v0Type, modes::V0::kAntiLambda)) { fillLambda(collisionBuilder, v0Products, v0, -1.f, posDaughterIndex, negDaughterIndex); - mcBuilder.template fillMcLambdaWithLabel(col, mcCols, v0, mcParticles, mcProducts); + mcBuilder.template fillMcLambdaWithLabel(v0, mcParticles, mcCols, mcProducts); } if constexpr (modes::isEqual(v0Type, modes::V0::kK0short)) { fillK0short(collisionBuilder, v0Products, v0, posDaughterIndex, negDaughterIndex); - mcBuilder.template fillMcK0shortWithLabel(col, mcCols, v0, mcParticles, mcProducts); + mcBuilder.template fillMcK0shortWithLabel(v0, mcParticles, mcCols, mcProducts); } } } @@ -713,6 +713,7 @@ class V0Builder } [[nodiscard]] bool fillAnyTable() const { return mFillAnyTable; } + [[nodiscard]] bool isPassThrough() const { return mV0Selection.isPassThrough(); } private: V0Selection mV0Selection; diff --git a/PWGCF/Femto/Core/v0HistManager.h b/PWGCF/Femto/Core/v0HistManager.h index 513862d6583..62199688116 100644 --- a/PWGCF/Femto/Core/v0HistManager.h +++ b/PWGCF/Femto/Core/v0HistManager.h @@ -420,13 +420,13 @@ class V0HistManager } } - template - void fill(T1 const& v0candidate, T2 const& tracks, T3 const& mcParticles, T4 const& mcMothers, T5 const& mcPartonicMothers) + template + void fill(T1 const& v0candidate, T2 const& tracks, T3 const& col, T4 const& mcParticles, T5 const& mcMothers, T6 const& mcPartonicMothers) { auto posDaughter = tracks.rawIteratorAt(v0candidate.posDauId() - tracks.offset()); - mPosDauManager.template fill(posDaughter, tracks, mcParticles, mcMothers, mcPartonicMothers); + mPosDauManager.template fill(posDaughter, tracks, col, mcParticles, mcMothers, mcPartonicMothers); auto negDaughter = tracks.rawIteratorAt(v0candidate.negDauId() - tracks.offset()); - mNegDauManager.template fill(negDaughter, tracks, mcParticles, mcMothers, mcPartonicMothers); + mNegDauManager.template fill(negDaughter, tracks, col, mcParticles, mcMothers, mcPartonicMothers); if constexpr (modes::isFlagSet(mode, modes::Mode::kReco)) { this->fillAnalysis(v0candidate); } @@ -434,7 +434,7 @@ class V0HistManager this->fillQa(v0candidate); } if constexpr (modes::isFlagSet(mode, modes::Mode::kMc)) { - this->template fillMc(v0candidate, mcParticles, mcMothers, mcPartonicMothers); + this->template fillMc(v0candidate, col, mcParticles, mcMothers, mcPartonicMothers); } } @@ -603,8 +603,8 @@ class V0HistManager } } - template - void fillMc(T1 const& v0Candidate, T2 const& /*mcParticles*/, T3 const& /*mcMothers*/, T4 const& /*mcPartonicMothers*/) + template + void fillMc(T1 const& v0Candidate, T2 const& col, T3 const& /*mcParticles*/, T4 const& /*mcMothers*/, T5 const& /*mcPartonicMothers*/) { // No MC Particle if (!v0Candidate.has_fMcParticle()) { @@ -619,16 +619,20 @@ class V0HistManager } // Retrieve MC particle - auto mcParticle = v0Candidate.template fMcParticle_as(); + auto mcParticle = v0Candidate.template fMcParticle_as(); + + // whether a particle is associated to a wrong collision or not cannot be known by the producer so we check it here + bool fromWrongCollision = mcParticle.fMcColId() != col.fMcColId(); - // missidentifed particles are special case // whether a particle is missidentfied or not cannot be known by the producer so we check it here bool isMissidentified = mcParticle.pdgCode() != mPdgCode; mHistogramRegistry->fill(HIST(v0Prefix) + HIST(McDir) + HIST(getHistName(kTruePtVsPt, HistTable)), mcParticle.pt(), v0Candidate.pt()); mHistogramRegistry->fill(HIST(v0Prefix) + HIST(McDir) + HIST(getHistName(kTrueEtaVsEta, HistTable)), mcParticle.eta(), v0Candidate.eta()); mHistogramRegistry->fill(HIST(v0Prefix) + HIST(McDir) + HIST(getHistName(kTruePhiVsPhi, HistTable)), mcParticle.phi(), v0Candidate.phi()); - if (isMissidentified) { + if (fromWrongCollision) { + mHistogramRegistry->fill(HIST(v0Prefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), static_cast(modes::McOrigin::kFromWrongCollision)); + } else if (isMissidentified) { mHistogramRegistry->fill(HIST(v0Prefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), static_cast(modes::McOrigin::kMissidentified)); } else { mHistogramRegistry->fill(HIST(v0Prefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), mcParticle.origin()); @@ -637,7 +641,7 @@ class V0HistManager // get mother if (mcParticle.has_fMcMother()) { - auto mother = mcParticle.template fMcMother_as(); + auto mother = mcParticle.template fMcMother_as(); mHistogramRegistry->fill(HIST(v0Prefix) + HIST(McDir) + HIST(getHistName(kPdgMother, HistTable)), mother.pdgCode()); } else { mHistogramRegistry->fill(HIST(v0Prefix) + HIST(McDir) + HIST(getHistName(kPdgMother, HistTable)), 0); @@ -645,7 +649,7 @@ class V0HistManager // get partonic mother if (mcParticle.has_fMcPartMoth()) { - auto partonicMother = mcParticle.template fMcPartMoth_as(); + auto partonicMother = mcParticle.template fMcPartMoth_as(); mHistogramRegistry->fill(HIST(v0Prefix) + HIST(McDir) + HIST(getHistName(kPdgPartonicMother, HistTable)), partonicMother.pdgCode()); } else { mHistogramRegistry->fill(HIST(v0Prefix) + HIST(McDir) + HIST(getHistName(kPdgPartonicMother, HistTable)), 0); @@ -654,7 +658,9 @@ class V0HistManager if constexpr (modes::isFlagSet(mode, modes::Mode::kQa)) { if (mPlotOrigins) { // check first if particle is missidentified - if (isMissidentified) { + if (fromWrongCollision) { + mHistogramRegistry->fill(HIST(v0Prefix) + HIST(McDir) + HIST(getHistName(kFromWrongCollision, HistTable)), v0Candidate.pt(), v0Candidate.cosPa()); + } else if (isMissidentified) { // if it is, we fill it as such mHistogramRegistry->fill(HIST(v0Prefix) + HIST(McDir) + HIST(getHistName(kMissidentified, HistTable)), v0Candidate.pt(), v0Candidate.cosPa()); } else { @@ -671,7 +677,7 @@ class V0HistManager break; case modes::McOrigin::kFromSecondaryDecay: if (mcParticle.has_fMcMother()) { - auto mother = mcParticle.template fMcMother_as(); + auto mother = mcParticle.template fMcMother_as(); int motherPdgCode = std::abs(mother.pdgCode()); // Switch on PDG of the mother if (mPlotNSecondaries >= histmanager::kSecondaryPlotLevel1 && motherPdgCode == mPdgCodesSecondaryMother[0]) { diff --git a/PWGCF/Femto/DataModel/FemtoTables.h b/PWGCF/Femto/DataModel/FemtoTables.h index 483cf8c67a9..aeecf703935 100644 --- a/PWGCF/Femto/DataModel/FemtoTables.h +++ b/PWGCF/Femto/DataModel/FemtoTables.h @@ -1063,6 +1063,78 @@ DECLARE_SOA_TABLE_STAGED_VERSIONED(FOmegaExtras_001, "FOMEGAEXTRA", 1, //! omega femtocascades::LambdaDcaToPv); using FOmegaExtras = FOmegaExtras_001; +namespace femtocharmhadrons +{ +// bitmask column +DECLARE_SOA_COLUMN(Mask, mask, o2::analysis::femto::datatypes::CharmHadronMaskType); //! selection bitmask + +// daughter links: row indices into the femto track table +DECLARE_SOA_INDEX_COLUMN_FULL(PosDau, posDau, int32_t, FTracks, "_PosDau"); //! + prong (pion in D0) +DECLARE_SOA_INDEX_COLUMN_FULL(NegDau, negDau, int32_t, FTracks, "_NegDau"); //! - prong (kaon in D0) + +// QA/debug columns +DECLARE_SOA_COLUMN(MassD0, massD0, float); //! Kpi-hypothesis mass +DECLARE_SOA_COLUMN(MassD0bar, massD0bar, float); //! piK-hypothesis mass +DECLARE_SOA_COLUMN(Cpa, cpa, float); +DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); +DECLARE_SOA_COLUMN(DecayLength, decayLength, float); +DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); +DECLARE_SOA_COLUMN(ImpactParameterProduct, impactParameterProduct, float); //! d0*d0 of the two prongs +DECLARE_SOA_COLUMN(CosThetaStar, cosThetaStar, float); +// ML BDT scores: [0] background, [1] prompt (D0 from c), [2] non-prompt (D0 from b decay) +DECLARE_SOA_COLUMN(MlProbD0Bkg, mlProbD0Bkg, float); //! D0 hypothesis: background score +DECLARE_SOA_COLUMN(MlProbD0Prompt, mlProbD0Prompt, float); //! D0 hypothesis: prompt score +DECLARE_SOA_COLUMN(MlProbD0NonPrompt, mlProbD0NonPrompt, float); //! D0 hypothesis: non-prompt score +DECLARE_SOA_COLUMN(MlProbD0barBkg, mlProbD0barBkg, float); //! D0bar hypothesis: background +DECLARE_SOA_COLUMN(MlProbD0barPrompt, mlProbD0barPrompt, float); //! D0bar hypothesis: prompt +DECLARE_SOA_COLUMN(MlProbD0barNonPrompt, mlProbD0barNonPrompt, float); //! D0bar hypothesis: non-prompt +DECLARE_SOA_COLUMN(IsSelD0, isSelD0, int8_t); //! PWGHF selection flag +DECLARE_SOA_COLUMN(IsSelD0bar, isSelD0bar, int8_t); //! PWGHF selection flag +} // namespace femtocharmhadrons + +DECLARE_SOA_TABLE_STAGED_VERSIONED(FD0s_001, "FD0", 1, //! femto D0/D0bar (kinematics only) + o2::soa::Index<>, + femtobase::stored::FColId, + femtobase::stored::SignedPt, //! sign encodes D0(+)/D0bar(-) + femtobase::stored::Eta, + femtobase::stored::Phi, + femtobase::stored::Mass, //! mass of the accepted hypothesis + femtocharmhadrons::PosDauId, + femtocharmhadrons::NegDauId, + femtobase::dynamic::Sign, + femtobase::dynamic::Pt, + femtobase::dynamic::P, + femtobase::dynamic::Px, + femtobase::dynamic::Py, + femtobase::dynamic::Pz, + femtobase::dynamic::Theta); +using FD0s = FD0s_001; +using StoredFD0s = StoredFD0s_001; + +DECLARE_SOA_TABLE_STAGED_VERSIONED(FD0Masks_001, "FD0MASK", 1, //! femto D0 selection bitmask + femtocharmhadrons::Mask); +using FD0Masks = FD0Masks_001; +using StoredFD0Masks = StoredFD0Masks_001; + +DECLARE_SOA_TABLE_STAGED_VERSIONED(FD0Extras_001, "FD0EXTRA", 1, //! femto D0 QA / debug + femtocharmhadrons::MassD0, // both hypotheses; the main + femtocharmhadrons::MassD0bar, // table only stores the accepted one + femtocharmhadrons::Cpa, + femtocharmhadrons::CpaXY, + femtocharmhadrons::DecayLength, + femtocharmhadrons::DecayLengthXY, + femtocharmhadrons::ImpactParameterProduct, + femtocharmhadrons::CosThetaStar, + femtocharmhadrons::MlProbD0Bkg, + femtocharmhadrons::MlProbD0Prompt, + femtocharmhadrons::MlProbD0NonPrompt, + femtocharmhadrons::MlProbD0barBkg, + femtocharmhadrons::MlProbD0barPrompt, + femtocharmhadrons::MlProbD0barNonPrompt, + femtocharmhadrons::IsSelD0, // raw PWGHF selection flags + femtocharmhadrons::IsSelD0bar); +using FD0Extras = FD0Extras_001; + // tables for monte carlo namespace femtomccollisions @@ -1162,76 +1234,5 @@ DECLARE_SOA_TABLE(FMcMotherLabels, "AOD", "FMCMOTHERLABEL", femtolabels::FMcMotherId, femtolabels::FMcPartMothId); -namespace femtocharmhadrons -{ -// bitmask column -DECLARE_SOA_COLUMN(Mask, mask, o2::analysis::femto::datatypes::CharmHadronMaskType); //! selection bitmask - -// daughter links: row indices into the femto track table -DECLARE_SOA_INDEX_COLUMN_FULL(PosDau, posDau, int32_t, FTracks, "_PosDau"); //! + prong (pion in D0) -DECLARE_SOA_INDEX_COLUMN_FULL(NegDau, negDau, int32_t, FTracks, "_NegDau"); //! - prong (kaon in D0) - -// QA/debug columns -DECLARE_SOA_COLUMN(MassD0, massD0, float); //! Kpi-hypothesis mass -DECLARE_SOA_COLUMN(MassD0bar, massD0bar, float); //! piK-hypothesis mass -DECLARE_SOA_COLUMN(Cpa, cpa, float); -DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); -DECLARE_SOA_COLUMN(DecayLength, decayLength, float); -DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); -DECLARE_SOA_COLUMN(ImpactParameterProduct, impactParameterProduct, float); //! d0*d0 of the two prongs -DECLARE_SOA_COLUMN(CosThetaStar, cosThetaStar, float); -// ML BDT scores: [0] background, [1] prompt (D0 from c), [2] non-prompt (D0 from b decay) -DECLARE_SOA_COLUMN(MlProbD0Bkg, mlProbD0Bkg, float); //! D0 hypothesis: background score -DECLARE_SOA_COLUMN(MlProbD0Prompt, mlProbD0Prompt, float); //! D0 hypothesis: prompt score -DECLARE_SOA_COLUMN(MlProbD0NonPrompt, mlProbD0NonPrompt, float); //! D0 hypothesis: non-prompt score -DECLARE_SOA_COLUMN(MlProbD0barBkg, mlProbD0barBkg, float); //! D0bar hypothesis: background -DECLARE_SOA_COLUMN(MlProbD0barPrompt, mlProbD0barPrompt, float); //! D0bar hypothesis: prompt -DECLARE_SOA_COLUMN(MlProbD0barNonPrompt, mlProbD0barNonPrompt, float); //! D0bar hypothesis: non-prompt -DECLARE_SOA_COLUMN(IsSelD0, isSelD0, int8_t); //! PWGHF selection flag -DECLARE_SOA_COLUMN(IsSelD0bar, isSelD0bar, int8_t); //! PWGHF selection flag -} // namespace femtocharmhadrons - -DECLARE_SOA_TABLE_STAGED_VERSIONED(FD0s_001, "FD0", 1, //! femto D0/D0bar (kinematics only) - o2::soa::Index<>, - femtobase::stored::FColId, - femtobase::stored::SignedPt, //! sign encodes D0(+)/D0bar(-) - femtobase::stored::Eta, - femtobase::stored::Phi, - femtobase::stored::Mass, //! mass of the accepted hypothesis - femtocharmhadrons::PosDauId, - femtocharmhadrons::NegDauId, - femtobase::dynamic::Sign, - femtobase::dynamic::Pt, - femtobase::dynamic::P, - femtobase::dynamic::Px, - femtobase::dynamic::Py, - femtobase::dynamic::Pz, - femtobase::dynamic::Theta); -using FD0s = FD0s_001; -using StoredFD0s = StoredFD0s_001; - -DECLARE_SOA_TABLE_STAGED_VERSIONED(FD0Masks_001, "FD0MASK", 1, //! femto D0 selection bitmask - femtocharmhadrons::Mask); -using FD0Masks = FD0Masks_001; -using StoredFD0Masks = StoredFD0Masks_001; - -DECLARE_SOA_TABLE_STAGED_VERSIONED(FD0Extras_001, "FD0EXTRA", 1, //! femto D0 QA / debug - femtocharmhadrons::MassD0, // both hypotheses; the main - femtocharmhadrons::MassD0bar, // table only stores the accepted one - femtocharmhadrons::Cpa, - femtocharmhadrons::CpaXY, - femtocharmhadrons::DecayLength, - femtocharmhadrons::DecayLengthXY, - femtocharmhadrons::ImpactParameterProduct, - femtocharmhadrons::CosThetaStar, - femtocharmhadrons::MlProbD0Bkg, - femtocharmhadrons::MlProbD0Prompt, - femtocharmhadrons::MlProbD0NonPrompt, - femtocharmhadrons::MlProbD0barBkg, - femtocharmhadrons::MlProbD0barPrompt, - femtocharmhadrons::MlProbD0barNonPrompt, - femtocharmhadrons::IsSelD0, // raw PWGHF selection flags - femtocharmhadrons::IsSelD0bar); -using FD0Extras = FD0Extras_001; } // namespace o2::aod #endif // PWGCF_FEMTO_DATAMODEL_FEMTOTABLES_H_ diff --git a/PWGCF/Femto/TableProducer/femtoProducer.cxx b/PWGCF/Femto/TableProducer/femtoProducer.cxx index 7a502163a49..f85e3bfa67d 100644 --- a/PWGCF/Femto/TableProducer/femtoProducer.cxx +++ b/PWGCF/Femto/TableProducer/femtoProducer.cxx @@ -44,11 +44,16 @@ #include #include #include +#include #include #include +#include #include #include +#include +#include +#include using namespace o2::analysis::femto; @@ -72,8 +77,8 @@ using Run3McRecoTracks = soa::Join; using Run3Vzeros = o2::aod::V0Datas; using Run3RecoVzeros = o2::soa::Join; -using Run3D0Candidates = soa::Join; -using Run3McD0Candidates = soa::Join; +using Run3D0s = soa::Join; +using Run3RecoD0s = soa::Join; using Run3Cascades = o2::aod::CascDatas; using Run3RecoCascades = o2::soa::Join; @@ -87,8 +92,13 @@ using Run3McGenParticles = o2::aod::McParticles; struct FemtoProducer { o2::framework::Preslice perMcCollision = o2::aod::mcparticle::mcCollisionId; + o2::framework::Preslice perColRecoTracks = o2::aod::track::collisionId; + o2::framework::Preslice perColRecoV0s = o2::aod::v0data::collisionId; + o2::framework::Preslice perColRecoCascades = o2::aod::cascdata::collisionId; + o2::framework::Preslice perColRecoKinks = o2::aod::kinkcand::collisionId; + o2::framework::Preslice perColRecoD0s = o2::aod::hf_cand::collisionId; - // ccdb + // ccdb config collisionbuilder::ConfCcdb confCcdb; // collision builder @@ -149,40 +159,15 @@ struct FemtoProducer { mcbuilder::McBuilder mcBuilder; // histogramming - // add histograms in next iteration o2::framework::HistogramRegistry hRegistry{"FemtoProducer", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; // data members o2::framework::Service ccdb = {}; /// Accessing the CCDB + o2::framework::Service pdgDb = {}; void init(o2::framework::InitContext& context) { - if ((xiBuilder.fillAnyTable() || omegaBuilder.fillAnyTable()) && - (!doprocessTracksV0sCascadesRun3pp && !doprocessTracksV0sCascadesRun3PbPb && - !doprocessTracksV0sCascadesKinksRun3pp && !doprocessTracksV0sCascadesRun3ppMc)) { - LOG(fatal) << "At least one cascade table is enabled, but wrong process function is enabled. Breaking..."; - } - if ((lambdaBuilder.fillAnyTable() || antilambdaBuilder.fillAnyTable() || k0shortBuilder.fillAnyTable()) && - (!doprocessTracksV0sCascadesRun3pp && !doprocessTracksV0sCascadesRun3PbPb && - !doprocessTracksV0sRun3pp && !doprocessTracksV0sCascadesKinksRun3pp && - !doprocessTracksV0sRun3ppMc && !doprocessTracksV0sRun3PbPb && !doprocessTracksV0sRun3PbPbMc && - !doprocessTracksV0sCascadesRun3ppMc && !doprocessTracksV0sKinksRun3ppMc)) { - LOG(fatal) << "At least one v0 table is enabled, but wrong process function is enabled. Breaking..."; - } - if ((sigmaBuilder.fillAnyTable() || sigmaPlusBuilder.fillAnyTable()) && - (!doprocessTracksKinksRun3pp && !doprocessTracksV0sCascadesKinksRun3pp && - !doprocessTracksKinksRun3ppMc && !doprocessTracksV0sKinksRun3ppMc)) { - LOG(fatal) << "At least one kink table is enabled, but wrong process function is enabled. Breaking..."; - } - if (mcBuilder.fillAnyTable() && - (!doprocessTracksV0sRun3ppMc && !doprocessTracksKinksRun3ppMc && - !doprocessTracksV0sCascadesRun3ppMc && !doprocessTracksV0sKinksRun3ppMc && - !doprocessTracksRun3ppMc && !doprocessTracksRun3PbPbMc && !doprocessTracksV0sRun3PbPbMc && - !doprocessMcOnly)) { - LOG(fatal) << "At least one mc table is enabled, but wrong process function is enabled. Breaking..."; - } - - // init ccdb + // ---- ccdb --------------------------------------------------------------- LOG(info) << "Setting up connection to CCDB with URL: " << confCcdb.ccdbUrl.value; ccdb->setURL(confCcdb.ccdbUrl.value); ccdb->setCaching(true); @@ -190,37 +175,104 @@ struct FemtoProducer { int64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); ccdb->setCreatedNotAfter(now); + // ---- builders ----------------------------------------------------------- // Order matters here: CollisionBuilder must init before TrackBuilder (which checks // collisionBuilder.producingCollisions()/producingLiteCollisions()), and TrackBuilder // must init before the V0/Cascade/Kink builders (which check // trackBuilder.producingTracks()/producingLiteTracks()). - - // configure collision builder collisionBuilder.init(&hRegistry, confCollisionFilters, confCollisionBits, confCollisionRctFlags, confCcdb, confCollisionTables, context); - - // configure track builder trackBuilder.init(&hRegistry, confTrackBits, confTrackFilters, confTrackTables, context, collisionBuilder); - // configure v0 builder k0shortBuilder.init(&hRegistry, confK0shortBits, confV0Filters, confV0Tables, context, trackBuilder); lambdaBuilder.init(&hRegistry, confLambdaBits, confV0Filters, confV0Tables, context, trackBuilder); antilambdaBuilder.init(&hRegistry, confLambdaBits, confV0Filters, confV0Tables, context, trackBuilder); - // configure d0 builder d0Builder.init(&hRegistry, confD0Bits, confD0Filters, confD0Tables, context); d0barBuilder.init(&hRegistry, confD0Bits, confD0Filters, confD0Tables, context); - // configure kink builder sigmaBuilder.init(&hRegistry, confSigmaBits, confKinkFilters, confKinkTables, context, trackBuilder); sigmaPlusBuilder.init(&hRegistry, confSigmaPlusBits, confKinkFilters, confKinkTables, context, trackBuilder); - // cascade selections xiBuilder.init(&hRegistry, confXiBits, confCascadeFilters, confCascadeTables, context, trackBuilder); omegaBuilder.init(&hRegistry, confOmegaBits, confCascadeFilters, confCascadeTables, context, trackBuilder); - // configure mcBuilder mcBuilder.init(confMc, confMcTables, context); + // ---- guard: enabled tables vs. enabled process function ------------------ + if ((xiBuilder.fillAnyTable() || omegaBuilder.fillAnyTable()) && + (!doprocessTracksV0sCascadesRun3pp && !doprocessTracksV0sCascadesRun3PbPb && + !doprocessTracksV0sCascadesKinksRun3pp && !doprocessTracksV0sCascadesRun3ppMc && + !doprocessTracksV0sCascadesRun3PbPbMc)) { + LOG(fatal) << "At least one cascade table is enabled, but wrong process function is enabled. Breaking..."; + } + if ((lambdaBuilder.fillAnyTable() || antilambdaBuilder.fillAnyTable() || k0shortBuilder.fillAnyTable()) && + (!doprocessTracksV0sCascadesRun3pp && !doprocessTracksV0sCascadesRun3PbPb && + !doprocessTracksV0sRun3pp && !doprocessTracksV0sCascadesKinksRun3pp && + !doprocessTracksV0sRun3ppMc && !doprocessTracksV0sRun3PbPb && !doprocessTracksV0sRun3PbPbMc && + !doprocessTracksV0sCascadesRun3ppMc && !doprocessTracksV0sCascadesRun3PbPbMc && + !doprocessTracksV0sKinksRun3ppMc)) { + LOG(fatal) << "At least one v0 table is enabled, but wrong process function is enabled. Breaking..."; + } + if ((sigmaBuilder.fillAnyTable() || sigmaPlusBuilder.fillAnyTable()) && + (!doprocessTracksKinksRun3pp && !doprocessTracksV0sCascadesKinksRun3pp && + !doprocessTracksKinksRun3ppMc && !doprocessTracksV0sKinksRun3ppMc)) { + LOG(fatal) << "At least one kink table is enabled, but wrong process function is enabled. Breaking..."; + } + if ((d0Builder.fillAnyTable() || d0barBuilder.fillAnyTable()) && + (!doprocessTracksD0sRun3pp && !doprocessTracksD0sRun3PbPb && + !doprocessTracksD0sRun3ppMc && !doprocessTracksD0sRun3PbPbMc)) { + LOG(fatal) << "At least one d0 table is enabled, but wrong process function is enabled. Breaking..."; + } + if (mcBuilder.fillAnyTable() && + (!doprocessTracksRun3ppMc && !doprocessTracksRun3PbPbMc && + !doprocessTracksV0sRun3ppMc && !doprocessTracksV0sRun3PbPbMc && + !doprocessTracksV0sCascadesRun3ppMc && !doprocessTracksV0sCascadesRun3PbPbMc && + !doprocessTracksKinksRun3ppMc && !doprocessTracksV0sKinksRun3ppMc && + !doprocessTracksD0sRun3ppMc && !doprocessTracksD0sRun3PbPbMc && + !doprocessMcOnly)) { + LOG(fatal) << "At least one mc table is enabled, but wrong process function is enabled. Breaking..."; + } + + // ---- guard: pass-through consistency across builders --------------------- + { + std::vector> passThroughFlags; + auto add = [&passThroughFlags](const std::string& name, bool enabled, bool passThrough) { + if (enabled) { + passThroughFlags.emplace_back(name, passThrough); + } + }; + // substitute the real accessors if they live on the builders rather than the conf groups + add("collision", collisionBuilder.fillAnyTable(), collisionBuilder.isPassThrough()); + add("track", trackBuilder.fillAnyTable(), trackBuilder.isPassThrough()); + add("k0short", k0shortBuilder.fillAnyTable(), k0shortBuilder.isPassThrough()); + add("lambda", lambdaBuilder.fillAnyTable(), lambdaBuilder.isPassThrough()); + add("antilambda", antilambdaBuilder.fillAnyTable(), antilambdaBuilder.isPassThrough()); + add("d0", d0Builder.fillAnyTable(), d0Builder.isPassThrough()); + add("d0bar", d0barBuilder.fillAnyTable(), d0barBuilder.isPassThrough()); + add("sigma", sigmaBuilder.fillAnyTable(), sigmaBuilder.isPassThrough()); + add("sigmaplus", sigmaPlusBuilder.fillAnyTable(), sigmaPlusBuilder.isPassThrough()); + add("xi", xiBuilder.fillAnyTable(), xiBuilder.isPassThrough()); + add("omega", omegaBuilder.fillAnyTable(), omegaBuilder.isPassThrough()); + add("mc", mcBuilder.fillAnyTable(), mcBuilder.isPassThrough()); + + const bool anyPassThrough = std::any_of(passThroughFlags.begin(), passThroughFlags.end(), + [](const auto& f) { return f.second; }); + const bool allPassThrough = std::all_of(passThroughFlags.begin(), passThroughFlags.end(), + [](const auto& f) { return f.second; }); + + if (anyPassThrough && !allPassThrough) { + LOG(warn) << "Builders disagree about pass-through mode:"; + for (const auto& [name, passThrough] : passThroughFlags) { + LOG(warn) << " " << name << " builder: pass-through = " << (passThrough ? "true" : "false"); + } + LOG(warn) << "This is legal, but check it is intended:"; + LOG(warn) << " - collisions in pass-through, particles not: every collision is written, " + << "but the particle tables only cover collisions with a candidate."; + LOG(warn) << " - particles in pass-through, collisions not: the extra particle rows hang off " + << "a candidate-biased event sample, which will bias event-normalised observables."; + } + } + hRegistry.print(); } @@ -231,21 +283,39 @@ struct FemtoProducer { collisionBuilder.reset(); auto bc = col.template bc_as(); collisionBuilder.initCollision(bc, col, tracks, ccdb, hRegistry); - // do not fill collsions into the table here - // collisions are filled if at least one partilce is found in the collisions - return collisionBuilder.checkCollision(col); + if (!collisionBuilder.checkCollision(col)) { + return false; + } + // Normally the collision row is written lazily, once a candidate is found. In + // pass-through we need every accepted collision, including those with no candidate, + // otherwise event-normalised observables lose exactly those events. + if (collisionBuilder.isPassThrough()) { + collisionBuilder.fillCollision(collisionBuilderProducts, col); + } + return true; } template bool processMcCollisions(T1 const& col, T2 const& mcCols, T3 const& /* bcs*/, T4 const& tracks, T5 const& mcParticles) { collisionBuilder.reset(); - mcBuilder.reset(mcCols, mcParticles); // we call this function always first so we reset the mcBuilder here + // in pass-through the maps are built once per timeframe + // resetting here would wipe them and duplicate every mc collision and particle + if (!mcBuilder.isPassThrough()) { + mcBuilder.reset(mcCols, mcParticles); + } auto bc = col.template bc_as(); collisionBuilder.initCollision(bc, col, tracks, ccdb, hRegistry); - // do not fill collsions into the table here - // collisions are filled if at least one partilce is found in the collisions - return collisionBuilder.checkCollision(col, mcCols); + if (!collisionBuilder.checkCollision(col, mcCols)) { + return false; + } + // NOTE: must be fillMcCollision, not fillCollision - fillMcCollision returns early on + // mCollisionAlreadyFilled, so filling the collision first would permanently skip + // the collision label + if (collisionBuilder.isPassThrough()) { + collisionBuilder.fillMcCollision(collisionBuilderProducts, col, mcCols, mcProducts, mcBuilder); + } + return true; } // processing tracks @@ -278,20 +348,6 @@ struct FemtoProducer { k0shortBuilder.fillMcV0s(col, collisionBuilder, collisionBuilderProducts, mcCols, trackBuilderProducts, v0builderProducts, v0s, tracks, trackBuilder, mcParticles, mcBuilder, mcProducts); } - // processing D0s - template - void processD0s(T1 const& col, T2 const& tracks, T3 const& candidates) - { - d0Builder.fillD0s(col, collisionBuilder, collisionBuilderProducts, trackBuilderProducts, charmHadronBuilderProducts, candidates, tracks, trackBuilder); - d0barBuilder.fillD0s(col, collisionBuilder, collisionBuilderProducts, trackBuilderProducts, charmHadronBuilderProducts, candidates, tracks, trackBuilder); - } - template - void processMcD0s(T1 const& col, T2 const& mcCols, T3 const& tracks, T4 const& candidates, T5 const& mcParticles) - { - d0Builder.fillMcD0s(col, collisionBuilder, collisionBuilderProducts, mcCols, trackBuilderProducts, charmHadronBuilderProducts, candidates, tracks, trackBuilder, mcParticles, mcBuilder, mcProducts); - d0barBuilder.fillMcD0s(col, collisionBuilder, collisionBuilderProducts, mcCols, trackBuilderProducts, charmHadronBuilderProducts, candidates, tracks, trackBuilder, mcParticles, mcBuilder, mcProducts); - } - // processing kinks template void processKinks(T1 const& col, T2 const& tracks, T3 const& kinks) @@ -322,7 +378,24 @@ struct FemtoProducer { omegaBuilder.fillMcCascades(col, collisionBuilder, collisionBuilderProducts, mcCols, trackBuilderProducts, cascadeBuilderProducts, cascades, tracks, trackBuilder, mcParticles, mcBuilder, mcProducts); } - // proccess functions + // processing D0s + template + void processD0s(T1 const& col, T2 const& tracks, T3 const& candidates) + { + d0Builder.fillD0s(col, collisionBuilder, collisionBuilderProducts, trackBuilderProducts, charmHadronBuilderProducts, candidates, tracks, trackBuilder); + d0barBuilder.fillD0s(col, collisionBuilder, collisionBuilderProducts, trackBuilderProducts, charmHadronBuilderProducts, candidates, tracks, trackBuilder); + } + template + void processMcD0s(T1 const& col, T2 const& mcCols, T3 const& tracks, T4 const& candidates, T5 const& mcParticles) + { + d0Builder.fillMcD0s(col, collisionBuilder, collisionBuilderProducts, mcCols, trackBuilderProducts, charmHadronBuilderProducts, candidates, tracks, trackBuilder, mcParticles, mcBuilder, mcProducts); + d0barBuilder.fillMcD0s(col, collisionBuilder, collisionBuilderProducts, mcCols, trackBuilderProducts, charmHadronBuilderProducts, candidates, tracks, trackBuilder, mcParticles, mcBuilder, mcProducts); + } + + // ========================================================================== + // process functions - data + // ========================================================================== + void processTracksRun3pp(rawinputs::Run3PpCollisions::iterator const& col, o2::aod::BCsWithTimestamps const& bcs, rawinputs::Run3FullPidTracks const& tracks) @@ -334,7 +407,7 @@ struct FemtoProducer { o2::aod::pidits::ITSNSigmaPr, o2::aod::pidits::ITSNSigmaDe, o2::aod::pidits::ITSNSigmaTr, o2::aod::pidits::ITSNSigmaHe>(tracks); processTracks(col, tracksWithItsPid); } - PROCESS_SWITCH(FemtoProducer, processTracksRun3pp, "Process tracks", true); + PROCESS_SWITCH(FemtoProducer, processTracksRun3pp, "Provide tracks", true); void processTracksRun3PbPb(rawinputs::Run3PbPbCollisions::iterator const& col, o2::aod::BCsWithTimestamps const& bcs, @@ -347,9 +420,8 @@ struct FemtoProducer { o2::aod::pidits::ITSNSigmaPr, o2::aod::pidits::ITSNSigmaDe, o2::aod::pidits::ITSNSigmaTr, o2::aod::pidits::ITSNSigmaHe>(tracks); processTracks(col, tracksWithItsPid); } - PROCESS_SWITCH(FemtoProducer, processTracksRun3PbPb, "Process tracks in PbPB collisions", false); + PROCESS_SWITCH(FemtoProducer, processTracksRun3PbPb, "Provide tracks in PbPb collisions", false); - // process tracks and v0s void processTracksV0sRun3pp(rawinputs::Run3PpCollisions::iterator const& col, o2::aod::BCsWithTimestamps const& bcs, rawinputs::Run3FullPidTracks const& tracks, @@ -362,8 +434,8 @@ struct FemtoProducer { o2::aod::pidits::ITSNSigmaPr, o2::aod::pidits::ITSNSigmaDe, o2::aod::pidits::ITSNSigmaTr, o2::aod::pidits::ITSNSigmaHe>(tracks); processTracks(col, tracksWithItsPid); processV0s(col, tracks, v0s); - }; - PROCESS_SWITCH(FemtoProducer, processTracksV0sRun3pp, "Process tracks and v0s", false); + } + PROCESS_SWITCH(FemtoProducer, processTracksV0sRun3pp, "Provide tracks and v0s", false); void processTracksV0sRun3PbPb(rawinputs::Run3PbPbCollisions::iterator const& col, o2::aod::BCsWithTimestamps const& bcs, @@ -377,14 +449,14 @@ struct FemtoProducer { o2::aod::pidits::ITSNSigmaPr, o2::aod::pidits::ITSNSigmaDe, o2::aod::pidits::ITSNSigmaTr, o2::aod::pidits::ITSNSigmaHe>(tracks); processTracks(col, tracksWithItsPid); processV0s(col, tracks, v0s); - }; - PROCESS_SWITCH(FemtoProducer, processTracksV0sRun3PbPb, "Process tracks and v0s in PbPB collisions", false); + } + PROCESS_SWITCH(FemtoProducer, processTracksV0sRun3PbPb, "Provide tracks and v0s in PbPb collisions", false); - // process tracks and D0s - void processTracksD0sRun3pp(rawinputs::Run3PpCollisions::iterator const& col, - o2::aod::BCsWithTimestamps const& bcs, - rawinputs::Run3FullPidTracks const& tracks, - rawinputs::Run3D0Candidates const& candidates) + void processTracksV0sCascadesRun3pp(rawinputs::Run3PpCollisions::iterator const& col, + o2::aod::BCsWithTimestamps const& bcs, + rawinputs::Run3FullPidTracks const& tracks, + rawinputs::Run3Vzeros const& v0s, + rawinputs::Run3Cascades const& cascades) { if (!processCollisions(col, bcs, tracks)) { return; @@ -392,14 +464,16 @@ struct FemtoProducer { auto tracksWithItsPid = o2::soa::Attach(tracks); processTracks(col, tracksWithItsPid); - processD0s(col, tracks, candidates); + processV0s(col, tracks, v0s); + processCascades(col, tracks, cascades); } - PROCESS_SWITCH(FemtoProducer, processTracksD0sRun3pp, "Process tracks and D0s", false); + PROCESS_SWITCH(FemtoProducer, processTracksV0sCascadesRun3pp, "Provide tracks, v0s and cascades", false); - void processTracksD0sRun3PbPb(rawinputs::Run3PbPbCollisions::iterator const& col, - o2::aod::BCsWithTimestamps const& bcs, - rawinputs::Run3FullPidTracks const& tracks, - rawinputs::Run3D0Candidates const& candidates) + void processTracksV0sCascadesRun3PbPb(rawinputs::Run3PbPbCollisions::iterator const& col, + o2::aod::BCsWithTimestamps const& bcs, + rawinputs::Run3FullPidTracks const& tracks, + rawinputs::Run3Vzeros const& v0s, + rawinputs::Run3Cascades const& cascades) { if (!processCollisions(col, bcs, tracks)) { return; @@ -407,46 +481,11 @@ struct FemtoProducer { auto tracksWithItsPid = o2::soa::Attach(tracks); processTracks(col, tracksWithItsPid); - processD0s(col, tracks, candidates); - } - PROCESS_SWITCH(FemtoProducer, processTracksD0sRun3PbPb, "Process tracks and D0s", false); - - // process monte carlo tracks and D0s - void processTracksD0sRun3ppMc(rawinputs::Run3PpMcRecoCollisions::iterator const& col, - rawinputs::Run3PpMcGenCollisions const& mcCols, - o2::aod::BCsWithTimestamps const& bcs, - rawinputs::Run3McRecoTracks const& tracks, - rawinputs::Run3McD0Candidates const& candidates, - rawinputs::Run3McGenParticles const& mcParticles) - { - if (!processMcCollisions(col, mcCols, bcs, tracks, mcParticles)) { - return; - } - auto tracksWithItsPid = o2::soa::Attach(tracks); - processMcTracks(col, mcCols, tracks, tracksWithItsPid, mcParticles); - processMcD0s(col, mcCols, tracks, candidates, mcParticles); - } - PROCESS_SWITCH(FemtoProducer, processTracksD0sRun3ppMc, "Provide reconstructed and generated tracks and D0s", false); - - void processTracksD0sRun3PbPbMc(rawinputs::Run3PbPbMcRecoCollisions::iterator const& col, - rawinputs::Run3PbPbMcGenCollisions const& mcCols, - o2::aod::BCsWithTimestamps const& bcs, - rawinputs::Run3McRecoTracks const& tracks, - rawinputs::Run3McD0Candidates const& candidates, - rawinputs::Run3McGenParticles const& mcParticles) - { - if (!processMcCollisions(col, mcCols, bcs, tracks, mcParticles)) { - return; - } - auto tracksWithItsPid = o2::soa::Attach(tracks); - processMcTracks(col, mcCols, tracks, tracksWithItsPid, mcParticles); - processMcD0s(col, mcCols, tracks, candidates, mcParticles); + processV0s(col, tracks, v0s); + processCascades(col, tracks, cascades); } - PROCESS_SWITCH(FemtoProducer, processTracksD0sRun3PbPbMc, "Provide reconstructed and generated tracks and D0s in PbPb collisions", false); + PROCESS_SWITCH(FemtoProducer, processTracksV0sCascadesRun3PbPb, "Provide tracks, v0s and cascades in PbPb collisions", false); - // process tracks and kinks void processTracksKinksRun3pp(rawinputs::Run3PpCollisions::iterator const& col, o2::aod::BCsWithTimestamps const& bcs, rawinputs::Run3FullPidTracks const& tracks, @@ -460,14 +499,14 @@ struct FemtoProducer { processTracks(col, tracksWithItsPid); processKinks(col, tracks, kinks); } - PROCESS_SWITCH(FemtoProducer, processTracksKinksRun3pp, "Process tracks and kinks", false); + PROCESS_SWITCH(FemtoProducer, processTracksKinksRun3pp, "Provide tracks and kinks", false); - // process tracks, v0s and cascades - void processTracksV0sCascadesRun3pp(rawinputs::Run3PpCollisions::iterator const& col, - o2::aod::BCsWithTimestamps const& bcs, - rawinputs::Run3FullPidTracks const& tracks, - rawinputs::Run3Vzeros const& v0s, - rawinputs::Run3Cascades const& cascades) + void processTracksV0sCascadesKinksRun3pp(rawinputs::Run3PpCollisions::iterator const& col, + o2::aod::BCsWithTimestamps const& bcs, + rawinputs::Run3FullPidTracks const& tracks, + rawinputs::Run3Vzeros const& v0s, + rawinputs::Run3Cascades const& cascades, + rawinputs::Run3Kinks const& kinks) { if (!processCollisions(col, bcs, tracks)) { return; @@ -477,178 +516,336 @@ struct FemtoProducer { processTracks(col, tracksWithItsPid); processV0s(col, tracks, v0s); processCascades(col, tracks, cascades); + processKinks(col, tracks, kinks); } - PROCESS_SWITCH(FemtoProducer, processTracksV0sCascadesRun3pp, "Provide Tracks, V0s and Cascades for Run3", false); + PROCESS_SWITCH(FemtoProducer, processTracksV0sCascadesKinksRun3pp, "Provide tracks, v0s, cascades and kinks", false); - void processTracksV0sCascadesRun3PbPb(rawinputs::Run3PbPbCollisions::iterator const& col, - o2::aod::BCsWithTimestamps const& bcs, - rawinputs::Run3FullPidTracks const& tracks, - rawinputs::Run3Vzeros const& v0s, - rawinputs::Run3Cascades const& cascades) + void processTracksD0sRun3pp(rawinputs::Run3PpCollisions::iterator const& col, + o2::aod::BCsWithTimestamps const& bcs, + rawinputs::Run3FullPidTracks const& tracks, + rawinputs::Run3D0s const& candidates) { - if (!processCollisions(col, bcs, tracks)) { + if (!processCollisions(col, bcs, tracks)) { return; } auto tracksWithItsPid = o2::soa::Attach(tracks); - processTracks(col, tracksWithItsPid); - processV0s(col, tracks, v0s); - processCascades(col, tracks, cascades); + processTracks(col, tracksWithItsPid); + processD0s(col, tracks, candidates); } - PROCESS_SWITCH(FemtoProducer, processTracksV0sCascadesRun3PbPb, "Provide Tracks, V0s and Cascades for Run3", false); + PROCESS_SWITCH(FemtoProducer, processTracksD0sRun3pp, "Provide tracks and D0s", false); - // process tracks, v0s, cascades and kinks - void processTracksV0sCascadesKinksRun3pp(rawinputs::Run3PpCollisions::iterator const& col, - o2::aod::BCsWithTimestamps const& bcs, - rawinputs::Run3FullPidTracks const& tracks, - rawinputs::Run3Vzeros const& v0s, - rawinputs::Run3Cascades const& cascades, - rawinputs::Run3Kinks const& kinks) + void processTracksD0sRun3PbPb(rawinputs::Run3PbPbCollisions::iterator const& col, + o2::aod::BCsWithTimestamps const& bcs, + rawinputs::Run3FullPidTracks const& tracks, + rawinputs::Run3D0s const& candidates) { - if (!processCollisions(col, bcs, tracks)) { + if (!processCollisions(col, bcs, tracks)) { return; } auto tracksWithItsPid = o2::soa::Attach(tracks); - processTracks(col, tracksWithItsPid); - processV0s(col, tracks, v0s); - processKinks(col, tracks, kinks); - processCascades(col, tracks, cascades); + processTracks(col, tracksWithItsPid); + processD0s(col, tracks, candidates); } - PROCESS_SWITCH(FemtoProducer, processTracksV0sCascadesKinksRun3pp, "Provide Tracks, V0s and Cascades for Run3", false); - - // process monte carlo tracks - void processTracksRun3ppMc(rawinputs::Run3PpMcRecoCollisions::iterator const& col, - rawinputs::Run3PpMcGenCollisions const& mcCols, + PROCESS_SWITCH(FemtoProducer, processTracksD0sRun3PbPb, "Provide tracks and D0s in PbPb collisions", false); + + // ========================================================================== + // process functions - monte carlo (ungrouped) + // + // No argument is an ::iterator, so DPL hands over the full timeframe tables and + // does no auto-grouping. Tables that are iterated over (tracks, v0s, cascades, + // kinks) are sliced per collision; the full track table is passed alongside so + // the v0/cascade/kink builders can resolve their daughter indices. + // These functions own the per-timeframe reset of the mc builder maps, which is + // why processMcCollisions skips its own reset in pass-through mode. + // ========================================================================== + + void processTracksRun3ppMc(rawinputs::Run3PpMcGenCollisions const& mcCols, + rawinputs::Run3PpMcRecoCollisions const& cols, o2::aod::BCsWithTimestamps const& bcs, rawinputs::Run3McRecoTracks const& tracks, rawinputs::Run3McGenParticles const& mcParticles) { - if (!processMcCollisions(col, mcCols, bcs, tracks, mcParticles)) { - return; + if (mcBuilder.isPassThrough()) { + mcBuilder.reset(mcCols, mcParticles); + mcBuilder.fillMcPassThrough(mcCols, mcParticles, perMcCollision, mcProducts, pdgDb); + } + + for (const auto& col : cols) { + auto tracksThisCol = tracks.sliceBy(perColRecoTracks, col.globalIndex()); + if (!processMcCollisions(col, mcCols, bcs, tracksThisCol, mcParticles)) { + continue; + } + auto tracksWithItsPid = o2::soa::Attach(tracksThisCol); + processMcTracks(col, mcCols, tracksThisCol, tracksWithItsPid, mcParticles); } - auto tracksWithItsPid = o2::soa::Attach(tracks); - processMcTracks(col, mcCols, tracks, tracksWithItsPid, mcParticles); } - PROCESS_SWITCH(FemtoProducer, processTracksRun3ppMc, "Provide reconstructed and generated Tracks", false); + PROCESS_SWITCH(FemtoProducer, processTracksRun3ppMc, "Provide reconstructed and generated tracks", false); - void processTracksRun3PbPbMc(rawinputs::Run3PbPbMcRecoCollisions::iterator const& col, - rawinputs::Run3PbPbMcGenCollisions const& mcCols, + void processTracksRun3PbPbMc(rawinputs::Run3PbPbMcGenCollisions const& mcCols, + rawinputs::Run3PbPbMcRecoCollisions const& cols, o2::aod::BCsWithTimestamps const& bcs, rawinputs::Run3McRecoTracks const& tracks, rawinputs::Run3McGenParticles const& mcParticles) { - if (!processMcCollisions(col, mcCols, bcs, tracks, mcParticles)) { - return; + if (mcBuilder.isPassThrough()) { + mcBuilder.reset(mcCols, mcParticles); + mcBuilder.fillMcPassThrough(mcCols, mcParticles, perMcCollision, mcProducts, pdgDb); + } + + for (const auto& col : cols) { + auto tracksThisCol = tracks.sliceBy(perColRecoTracks, col.globalIndex()); + if (!processMcCollisions(col, mcCols, bcs, tracksThisCol, mcParticles)) { + continue; + } + auto tracksWithItsPid = o2::soa::Attach(tracksThisCol); + processMcTracks(col, mcCols, tracksThisCol, tracksWithItsPid, mcParticles); } - auto tracksWithItsPid = o2::soa::Attach(tracks); - processMcTracks(col, mcCols, tracks, tracksWithItsPid, mcParticles); } - PROCESS_SWITCH(FemtoProducer, processTracksRun3PbPbMc, "Provide reconstructed and generated Tracks in PbPb collisions", false); + PROCESS_SWITCH(FemtoProducer, processTracksRun3PbPbMc, "Provide reconstructed and generated tracks in PbPb collisions", false); - // process monte carlo tracks and v0s - void processTracksV0sRun3ppMc(rawinputs::Run3PpMcRecoCollisions::iterator const& col, - rawinputs::Run3PpMcGenCollisions const& mcCols, + void processTracksV0sRun3ppMc(rawinputs::Run3PpMcGenCollisions const& mcCols, + rawinputs::Run3PpMcRecoCollisions const& cols, o2::aod::BCsWithTimestamps const& bcs, rawinputs::Run3McRecoTracks const& tracks, rawinputs::Run3RecoVzeros const& v0s, rawinputs::Run3McGenParticles const& mcParticles) { - if (!processMcCollisions(col, mcCols, bcs, tracks, mcParticles)) { - return; + if (mcBuilder.isPassThrough()) { + mcBuilder.reset(mcCols, mcParticles); + mcBuilder.fillMcPassThrough(mcCols, mcParticles, perMcCollision, mcProducts, pdgDb); + } + + for (const auto& col : cols) { + auto tracksThisCol = tracks.sliceBy(perColRecoTracks, col.globalIndex()); + if (!processMcCollisions(col, mcCols, bcs, tracksThisCol, mcParticles)) { + continue; + } + auto tracksWithItsPid = o2::soa::Attach(tracksThisCol); + processMcTracks(col, mcCols, tracksThisCol, tracksWithItsPid, mcParticles); + + auto v0sThisCol = v0s.sliceBy(perColRecoV0s, col.globalIndex()); + processMcV0s(col, mcCols, tracks, v0sThisCol, mcParticles); } - auto tracksWithItsPid = o2::soa::Attach(tracks); - processMcTracks(col, mcCols, tracks, tracksWithItsPid, mcParticles); - processMcV0s(col, mcCols, tracks, v0s, mcParticles); } PROCESS_SWITCH(FemtoProducer, processTracksV0sRun3ppMc, "Provide reconstructed and generated tracks and v0s", false); - void processTracksV0sRun3PbPbMc(rawinputs::Run3PbPbMcRecoCollisions::iterator const& col, - rawinputs::Run3PbPbMcGenCollisions const& mcCols, + void processTracksV0sRun3PbPbMc(rawinputs::Run3PbPbMcGenCollisions const& mcCols, + rawinputs::Run3PbPbMcRecoCollisions const& cols, o2::aod::BCsWithTimestamps const& bcs, rawinputs::Run3McRecoTracks const& tracks, rawinputs::Run3RecoVzeros const& v0s, rawinputs::Run3McGenParticles const& mcParticles) { - if (!processMcCollisions(col, mcCols, bcs, tracks, mcParticles)) { - return; + if (mcBuilder.isPassThrough()) { + mcBuilder.reset(mcCols, mcParticles); + mcBuilder.fillMcPassThrough(mcCols, mcParticles, perMcCollision, mcProducts, pdgDb); + } + + for (const auto& col : cols) { + auto tracksThisCol = tracks.sliceBy(perColRecoTracks, col.globalIndex()); + if (!processMcCollisions(col, mcCols, bcs, tracksThisCol, mcParticles)) { + continue; + } + auto tracksWithItsPid = o2::soa::Attach(tracksThisCol); + processMcTracks(col, mcCols, tracksThisCol, tracksWithItsPid, mcParticles); + + auto v0sThisCol = v0s.sliceBy(perColRecoV0s, col.globalIndex()); + processMcV0s(col, mcCols, tracks, v0sThisCol, mcParticles); } - auto tracksWithItsPid = o2::soa::Attach(tracks); - processMcTracks(col, mcCols, tracks, tracksWithItsPid, mcParticles); - processMcV0s(col, mcCols, tracks, v0s, mcParticles); } PROCESS_SWITCH(FemtoProducer, processTracksV0sRun3PbPbMc, "Provide reconstructed and generated tracks and v0s in PbPb collisions", false); - // process monte carlo tracks and kinks - void processTracksKinksRun3ppMc(rawinputs::Run3PpMcRecoCollisions::iterator const& col, - rawinputs::Run3PpMcGenCollisions const& mcCols, + void processTracksV0sCascadesRun3ppMc(rawinputs::Run3PpMcGenCollisions const& mcCols, + rawinputs::Run3PpMcRecoCollisions const& cols, + o2::aod::BCsWithTimestamps const& bcs, + rawinputs::Run3McRecoTracks const& tracks, + rawinputs::Run3RecoVzeros const& v0s, + rawinputs::Run3RecoCascades const& cascades, + rawinputs::Run3McGenParticles const& mcParticles) + { + if (mcBuilder.isPassThrough()) { + mcBuilder.reset(mcCols, mcParticles); + mcBuilder.fillMcPassThrough(mcCols, mcParticles, perMcCollision, mcProducts, pdgDb); + } + + for (const auto& col : cols) { + auto tracksThisCol = tracks.sliceBy(perColRecoTracks, col.globalIndex()); + if (!processMcCollisions(col, mcCols, bcs, tracksThisCol, mcParticles)) { + continue; + } + auto tracksWithItsPid = o2::soa::Attach(tracksThisCol); + processMcTracks(col, mcCols, tracksThisCol, tracksWithItsPid, mcParticles); + + auto v0sThisCol = v0s.sliceBy(perColRecoV0s, col.globalIndex()); + processMcV0s(col, mcCols, tracks, v0sThisCol, mcParticles); + + auto cascadesThisCol = cascades.sliceBy(perColRecoCascades, col.globalIndex()); + processMcCascades(col, mcCols, tracks, cascadesThisCol, mcParticles); + } + } + PROCESS_SWITCH(FemtoProducer, processTracksV0sCascadesRun3ppMc, "Provide reconstructed and generated tracks, v0s and cascades", false); + + void processTracksV0sCascadesRun3PbPbMc(rawinputs::Run3PbPbMcGenCollisions const& mcCols, + rawinputs::Run3PbPbMcRecoCollisions const& cols, + o2::aod::BCsWithTimestamps const& bcs, + rawinputs::Run3McRecoTracks const& tracks, + rawinputs::Run3RecoVzeros const& v0s, + rawinputs::Run3RecoCascades const& cascades, + rawinputs::Run3McGenParticles const& mcParticles) + { + if (mcBuilder.isPassThrough()) { + mcBuilder.reset(mcCols, mcParticles); + mcBuilder.fillMcPassThrough(mcCols, mcParticles, perMcCollision, mcProducts, pdgDb); + } + + for (const auto& col : cols) { + auto tracksThisCol = tracks.sliceBy(perColRecoTracks, col.globalIndex()); + if (!processMcCollisions(col, mcCols, bcs, tracksThisCol, mcParticles)) { + continue; + } + auto tracksWithItsPid = o2::soa::Attach(tracksThisCol); + processMcTracks(col, mcCols, tracksThisCol, tracksWithItsPid, mcParticles); + + auto v0sThisCol = v0s.sliceBy(perColRecoV0s, col.globalIndex()); + processMcV0s(col, mcCols, tracks, v0sThisCol, mcParticles); + + auto cascadesThisCol = cascades.sliceBy(perColRecoCascades, col.globalIndex()); + processMcCascades(col, mcCols, tracks, cascadesThisCol, mcParticles); + } + } + PROCESS_SWITCH(FemtoProducer, processTracksV0sCascadesRun3PbPbMc, "Provide reconstructed and generated tracks, v0s and cascades in PbPb collisions", false); + + void processTracksKinksRun3ppMc(rawinputs::Run3PpMcGenCollisions const& mcCols, + rawinputs::Run3PpMcRecoCollisions const& cols, o2::aod::BCsWithTimestamps const& bcs, rawinputs::Run3McRecoTracks const& tracks, rawinputs::Run3Kinks const& kinks, rawinputs::Run3McGenParticles const& mcParticles) { - if (!processMcCollisions(col, mcCols, bcs, tracks, mcParticles)) { - return; + if (mcBuilder.isPassThrough()) { + mcBuilder.reset(mcCols, mcParticles); + mcBuilder.fillMcPassThrough(mcCols, mcParticles, perMcCollision, mcProducts, pdgDb); + } + + for (const auto& col : cols) { + auto tracksThisCol = tracks.sliceBy(perColRecoTracks, col.globalIndex()); + if (!processMcCollisions(col, mcCols, bcs, tracksThisCol, mcParticles)) { + continue; + } + auto tracksWithItsPid = o2::soa::Attach(tracksThisCol); + processMcTracks(col, mcCols, tracksThisCol, tracksWithItsPid, mcParticles); + + auto kinksThisCol = kinks.sliceBy(perColRecoKinks, col.globalIndex()); + processMcKinks(col, mcCols, tracks, kinksThisCol, mcParticles); } - auto tracksWithItsPid = o2::soa::Attach(tracks); - processMcTracks(col, mcCols, tracks, tracksWithItsPid, mcParticles); - processMcKinks(col, mcCols, tracks, kinks, mcParticles); } PROCESS_SWITCH(FemtoProducer, processTracksKinksRun3ppMc, "Provide reconstructed and generated tracks and kinks", false); - // process monte carlo tracks and v0s and kinks (adding cascades later here) - void processTracksV0sKinksRun3ppMc(rawinputs::Run3PpMcRecoCollisions::iterator const& col, - rawinputs::Run3PpMcGenCollisions const& mcCols, + void processTracksV0sKinksRun3ppMc(rawinputs::Run3PpMcGenCollisions const& mcCols, + rawinputs::Run3PpMcRecoCollisions const& cols, o2::aod::BCsWithTimestamps const& bcs, rawinputs::Run3McRecoTracks const& tracks, rawinputs::Run3RecoVzeros const& v0s, rawinputs::Run3Kinks const& kinks, rawinputs::Run3McGenParticles const& mcParticles) { - if (!processMcCollisions(col, mcCols, bcs, tracks, mcParticles)) { - return; + if (mcBuilder.isPassThrough()) { + mcBuilder.reset(mcCols, mcParticles); + mcBuilder.fillMcPassThrough(mcCols, mcParticles, perMcCollision, mcProducts, pdgDb); + } + + for (const auto& col : cols) { + auto tracksThisCol = tracks.sliceBy(perColRecoTracks, col.globalIndex()); + if (!processMcCollisions(col, mcCols, bcs, tracksThisCol, mcParticles)) { + continue; + } + auto tracksWithItsPid = o2::soa::Attach(tracksThisCol); + processMcTracks(col, mcCols, tracksThisCol, tracksWithItsPid, mcParticles); + + auto v0sThisCol = v0s.sliceBy(perColRecoV0s, col.globalIndex()); + processMcV0s(col, mcCols, tracks, v0sThisCol, mcParticles); + + auto kinksThisCol = kinks.sliceBy(perColRecoKinks, col.globalIndex()); + processMcKinks(col, mcCols, tracks, kinksThisCol, mcParticles); } - auto tracksWithItsPid = o2::soa::Attach(tracks); - processMcTracks(col, mcCols, tracks, tracksWithItsPid, mcParticles); - processMcV0s(col, mcCols, tracks, v0s, mcParticles); - processMcKinks(col, mcCols, tracks, kinks, mcParticles); } - PROCESS_SWITCH(FemtoProducer, processTracksV0sKinksRun3ppMc, "Provide reconstructed and generated tracks and v0s and kinks", false); + PROCESS_SWITCH(FemtoProducer, processTracksV0sKinksRun3ppMc, "Provide reconstructed and generated tracks, v0s and kinks", false); - // process monte carlo tracks and v0s - void processTracksV0sCascadesRun3ppMc(rawinputs::Run3PpMcRecoCollisions::iterator const& col, - rawinputs::Run3PpMcGenCollisions const& mcCols, - o2::aod::BCsWithTimestamps const& bcs, - rawinputs::Run3McRecoTracks const& tracks, - rawinputs::Run3RecoVzeros const& v0s, - rawinputs::Run3RecoCascades const& cascades, - rawinputs::Run3McGenParticles const& mcParticles) + void processTracksD0sRun3ppMc(rawinputs::Run3PpMcGenCollisions const& mcCols, + rawinputs::Run3PpMcRecoCollisions const& cols, + o2::aod::BCsWithTimestamps const& bcs, + rawinputs::Run3McRecoTracks const& tracks, + rawinputs::Run3RecoD0s const& d0s, + rawinputs::Run3McGenParticles const& mcParticles) { - if (!processMcCollisions(col, mcCols, bcs, tracks, mcParticles)) { - return; + if (mcBuilder.isPassThrough()) { + mcBuilder.reset(mcCols, mcParticles); + mcBuilder.fillMcPassThrough(mcCols, mcParticles, perMcCollision, mcProducts, pdgDb); + } + + for (const auto& col : cols) { + auto tracksThisCol = tracks.sliceBy(perColRecoTracks, col.globalIndex()); + if (!processMcCollisions(col, mcCols, bcs, tracksThisCol, mcParticles)) { + continue; + } + auto tracksWithItsPid = o2::soa::Attach(tracksThisCol); + processMcTracks(col, mcCols, tracksThisCol, tracksWithItsPid, mcParticles); + + auto d0sThisCol = d0s.sliceBy(perColRecoD0s, col.globalIndex()); + processMcD0s(col, mcCols, tracks, d0sThisCol, mcParticles); } - auto tracksWithItsPid = o2::soa::Attach(tracks); - processMcTracks(col, mcCols, tracks, tracksWithItsPid, mcParticles); - processMcV0s(col, mcCols, tracks, v0s, mcParticles); - processMcCascades(col, mcCols, tracks, cascades, mcParticles); } - PROCESS_SWITCH(FemtoProducer, processTracksV0sCascadesRun3ppMc, "Provide reconstructed and generated tracks and v0s", false); + PROCESS_SWITCH(FemtoProducer, processTracksD0sRun3ppMc, "Provide reconstructed and generated tracks and D0s", false); + + void processTracksD0sRun3PbPbMc(rawinputs::Run3PbPbMcGenCollisions const& mcCols, + rawinputs::Run3PbPbMcRecoCollisions const& cols, + o2::aod::BCsWithTimestamps const& bcs, + rawinputs::Run3McRecoTracks const& tracks, + rawinputs::Run3RecoD0s const& d0s, + rawinputs::Run3McGenParticles const& mcParticles) + { + if (mcBuilder.isPassThrough()) { + mcBuilder.reset(mcCols, mcParticles); + mcBuilder.fillMcPassThrough(mcCols, mcParticles, perMcCollision, mcProducts, pdgDb); + } + + for (const auto& col : cols) { + auto tracksThisCol = tracks.sliceBy(perColRecoTracks, col.globalIndex()); + if (!processMcCollisions(col, mcCols, bcs, tracksThisCol, mcParticles)) { + continue; + } + auto tracksWithItsPid = o2::soa::Attach(tracksThisCol); + processMcTracks(col, mcCols, tracksThisCol, tracksWithItsPid, mcParticles); + + auto d0sThisCol = d0s.sliceBy(perColRecoD0s, col.globalIndex()); + processMcD0s(col, mcCols, tracks, d0sThisCol, mcParticles); + } + } + PROCESS_SWITCH(FemtoProducer, processTracksD0sRun3PbPbMc, "Provide reconstructed and generated tracks and D0s in PbPb collisions", false); + + // ========================================================================== + // process functions - generator level only (for MCGEN datasets) + // ========================================================================== - // process generator level only input (for MCGEN datasets) - // do not preslice mcParticles tables for each collision, otherwise the finding of the partonic mother can fail + // do not preslice the mcParticles table passed to fillMcParticle, otherwise the finding of the partonic mother can fail void processMcOnly(o2::aod::McCollisions const& mcCols, o2::aod::McParticles const& mcParticles) { - mcBuilder.reset(mcParticles); + mcBuilder.reset(mcCols, mcParticles); for (const auto& mcCol : mcCols) { - mcBuilder.fillMcCollision(mcCol, mcParticles, mcProducts); auto particlesThisCollision = mcParticles.sliceBy(perMcCollision, mcCol.globalIndex()); + mcBuilder.fillMcCollision(mcCol, particlesThisCollision, mcProducts, pdgDb); for (const auto& mcParticle : particlesThisCollision) { mcBuilder.fillMcParticle(mcParticle, mcParticles, mcCol, mcProducts); } diff --git a/PWGCF/Femto/Tasks/femtoCascadeQa.cxx b/PWGCF/Femto/Tasks/femtoCascadeQa.cxx index 9b627838165..e7b9eeaa842 100644 --- a/PWGCF/Femto/Tasks/femtoCascadeQa.cxx +++ b/PWGCF/Femto/Tasks/femtoCascadeQa.cxx @@ -195,7 +195,7 @@ struct FemtoCascadeQa { if (!xiCleaner.isClean(xi, mcParticles, mcMothers, mcPartonicMothers)) { continue; } - xiHistManager.fill(xi, tracks, mcParticles, mcMothers, mcPartonicMothers); + xiHistManager.fill(xi, tracks, col, mcParticles, mcMothers, mcPartonicMothers); } } PROCESS_SWITCH(FemtoCascadeQa, processXiMc, "Process Xis with MC information", false); @@ -224,7 +224,7 @@ struct FemtoCascadeQa { if (!omegaCleaner.isClean(omega, mcParticles, mcMothers, mcPartonicMothers)) { continue; } - omegaHistManager.fill(omega, tracks, mcParticles, mcMothers, mcPartonicMothers); + omegaHistManager.fill(omega, tracks, col, mcParticles, mcMothers, mcPartonicMothers); } } PROCESS_SWITCH(FemtoCascadeQa, processOmegaMc, "Process Omegas with MC information", false); diff --git a/PWGCF/Femto/Tasks/femtoD0Qa.cxx b/PWGCF/Femto/Tasks/femtoD0Qa.cxx index 7a3f9330722..c1222f52a80 100644 --- a/PWGCF/Femto/Tasks/femtoD0Qa.cxx +++ b/PWGCF/Femto/Tasks/femtoD0Qa.cxx @@ -146,7 +146,7 @@ struct FemtoD0Qa { } colHistManager.fill(col, mcCols); for (auto const& d0 : d0Slice) { - d0HistManager.fill(d0, tracks, mcParticles, mcMothers, mcPartonicMothers); + d0HistManager.fill(d0, tracks, col, mcParticles, mcMothers, mcPartonicMothers); } } PROCESS_SWITCH(FemtoD0Qa, processD0Mc, "Process D0s with MC information", false); diff --git a/PWGCF/Femto/Tasks/femtoKinkQa.cxx b/PWGCF/Femto/Tasks/femtoKinkQa.cxx index 877c0905b83..88c56762db3 100644 --- a/PWGCF/Femto/Tasks/femtoKinkQa.cxx +++ b/PWGCF/Femto/Tasks/femtoKinkQa.cxx @@ -186,7 +186,7 @@ struct FemtoKinkQa { if (!sigmaCleaner.isClean(sigma, mcParticles, mcMothers, mcPartonicMothers)) { continue; } - sigmaHistManager.fill(sigma, tracks, mcParticles, mcMothers, mcPartonicMothers); + sigmaHistManager.fill(sigma, tracks, col, mcParticles, mcMothers, mcPartonicMothers); } } PROCESS_SWITCH(FemtoKinkQa, processSigmaMc, "Process sigmas", false); @@ -215,7 +215,7 @@ struct FemtoKinkQa { if (!sigmaPlusCleaner.isClean(sigmaPlus, mcParticles, mcMothers, mcPartonicMothers)) { continue; } - sigmaPlusHistManager.fill(sigmaPlus, tracks, mcParticles, mcMothers, mcPartonicMothers); + sigmaPlusHistManager.fill(sigmaPlus, tracks, col, mcParticles, mcMothers, mcPartonicMothers); } } PROCESS_SWITCH(FemtoKinkQa, processSigmaPlusMc, "Process sigmas", false); diff --git a/PWGCF/Femto/Tasks/femtoTrackQa.cxx b/PWGCF/Femto/Tasks/femtoTrackQa.cxx index 88583914287..bdd7de9580a 100644 --- a/PWGCF/Femto/Tasks/femtoTrackQa.cxx +++ b/PWGCF/Femto/Tasks/femtoTrackQa.cxx @@ -130,7 +130,7 @@ struct FemtoTrackQa { if (!trackCleaner.isClean(track, mcParticles, mcMothers, mcPartonicMothers)) { continue; } - trackHistManager.fill(track, tracks, mcParticles, mcMothers, mcPartonicMothers); + trackHistManager.fill(track, tracks, col, mcParticles, mcMothers, mcPartonicMothers); } } PROCESS_SWITCH(FemtoTrackQa, processMc, "Track QA in Monte Carlo", false); diff --git a/PWGCF/Femto/Tasks/femtoV0Qa.cxx b/PWGCF/Femto/Tasks/femtoV0Qa.cxx index 5567532fcbc..ceba51e509d 100644 --- a/PWGCF/Femto/Tasks/femtoV0Qa.cxx +++ b/PWGCF/Femto/Tasks/femtoV0Qa.cxx @@ -190,7 +190,7 @@ struct FemtoV0Qa { if (!k0shortCleaner.isClean(k0short, mcParticles, mcMothers, mcPartonicMothers)) { continue; } - k0shortHistManager.fill(k0short, tracks, mcParticles, mcMothers, mcPartonicMothers); + k0shortHistManager.fill(k0short, tracks, col, mcParticles, mcMothers, mcPartonicMothers); } } PROCESS_SWITCH(FemtoV0Qa, processK0shortMc, "Process k0shorts with MC information", false); @@ -219,7 +219,7 @@ struct FemtoV0Qa { if (!lambdaCleaner.isClean(lambda, mcParticles, mcMothers, mcPartonicMothers)) { continue; } - lambdaHistManager.fill(lambda, tracks, mcParticles, mcMothers, mcPartonicMothers); + lambdaHistManager.fill(lambda, tracks, col, mcParticles, mcMothers, mcPartonicMothers); } } PROCESS_SWITCH(FemtoV0Qa, processLambdaMc, "Process lambdas with MC informaton", false);