From c70c495ddf0fe8686e197ef6926a2aca1ed9d4f1 Mon Sep 17 00:00:00 2001 From: jesgum Date: Tue, 26 May 2026 17:13:27 +0200 Subject: [PATCH 01/12] store wip --- ALICE3/Core/OTFParticle.h | 1 + ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx | 66 ++++++++++++-------- ALICE3/Tasks/alice3DecayerQa.cxx | 16 ++--- 3 files changed, 48 insertions(+), 35 deletions(-) diff --git a/ALICE3/Core/OTFParticle.h b/ALICE3/Core/OTFParticle.h index b6ca1f246c3..c66fc73665f 100644 --- a/ALICE3/Core/OTFParticle.h +++ b/ALICE3/Core/OTFParticle.h @@ -27,6 +27,7 @@ namespace o2::upgrade { +static constexpr uint8_t ProducedByDecayer = 0xFF; class OTFParticle { diff --git a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx index ae0d61bcd82..f79f78c778e 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx @@ -67,12 +67,15 @@ static const std::vector pdgCodes{PDG_t::kK0Short, PDG_t::kOmegaMinus, PDG_t::kOmegaPlusBar}; +// Witchcraft +namespace o2::aod { O2ORIGIN("TMP"); } + struct OnTheFlyDecayer { - Produces tableMcParticlesWithDau; + Produces tableMcCollisions; + Produces tableMcParticles; o2::upgrade::Decayer decayer; Service pdgDB; - std::map> mDecayDaughters; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; Configurable seed{"seed", 0, "Set seed for particle decayer"}; @@ -165,37 +168,46 @@ struct OnTheFlyDecayer { decayParticles(stop, stop + ndau); } - void process(aod::McCollision const& collision, aod::McParticles const& mcParticles) + void process(aod::McCollisions_001/*From>*/ const& mcCollisions, aod::McParticles_001From> const& mcParticles) { - mCollisionId = collision.globalIndex(); - allParticles.clear(); + for (const auto& collision : mcCollisions) { + allParticles.clear(); + mCollisionId = collision.globalIndex(); + tableMcCollisions(collision.bcId(), + collision.generatorsID(), + collision.posX(), + collision.posY(), + collision.posZ(), + collision.t(), + collision.weight(), + collision.impactParameter(), + collision.eventPlaneAngle()); + + // First we copy the particles from the table into a vector that is extendable + for (int index{0}; index < static_cast(mcParticles.size()); ++index) { + const auto& mcParticle = mcParticles.rawIteratorAt(index); + allParticles.push_back(o2::upgrade::OTFParticle{mcParticle}); + } - // First we copy the particles from the table into a vector that is extendable - for (int index{0}; index < static_cast(mcParticles.size()); ++index) { - const auto& mcParticle = mcParticles.rawIteratorAt(index); - allParticles.push_back(o2::upgrade::OTFParticle{mcParticle}); - } + // Do all decays + decayParticles(0, allParticles.size()); - // Do all decays - decayParticles(0, allParticles.size()); + // Fill output table + for (int index{0}; index < static_cast(allParticles.size()); ++index) { + const auto& otfParticle = allParticles[index]; - // Fill output table - for (int index{0}; index < static_cast(allParticles.size()); ++index) { - const auto& otfParticle = allParticles[index]; + if (otfParticle.hasNaN()) { + histos.fill(HIST("hNaNBookkeeping"), 1); + } else { + histos.fill(HIST("hNaNBookkeeping"), 0); + } - if (otfParticle.hasNaN()) { - histos.fill(HIST("hNaNBookkeeping"), 1); - } else { - histos.fill(HIST("hNaNBookkeeping"), 0); + // todo: status codes + tableMcParticles(otfParticle.collisionId(), otfParticle.pdgCode(), otfParticle.statusCode(), otfParticle.flags(), + otfParticle.getMotherSpan(), otfParticle.getDaughters().data(), otfParticle.weight(), + otfParticle.px(), otfParticle.py(), otfParticle.pz(), otfParticle.e(), + otfParticle.vx(), otfParticle.vy(), otfParticle.vz(), otfParticle.vt()); } - - // todo: status codes - tableMcParticlesWithDau(otfParticle.collisionId(), otfParticle.pdgCode(), otfParticle.statusCode(), - otfParticle.flags(), otfParticle.getMotherSpan(), otfParticle.getDaughters().data(), otfParticle.weight(), - otfParticle.px(), otfParticle.py(), otfParticle.pz(), otfParticle.e(), - otfParticle.vx(), otfParticle.vy(), otfParticle.vz(), otfParticle.vt(), - otfParticle.phi(), otfParticle.eta(), otfParticle.pt(), otfParticle.p(), otfParticle.y(), - otfParticle.isAlive(), otfParticle.isPrimary()); } } }; diff --git a/ALICE3/Tasks/alice3DecayerQa.cxx b/ALICE3/Tasks/alice3DecayerQa.cxx index 5ae57d33f66..d4d41a8ae7e 100644 --- a/ALICE3/Tasks/alice3DecayerQa.cxx +++ b/ALICE3/Tasks/alice3DecayerQa.cxx @@ -61,14 +61,14 @@ struct Alice3DecayerQa { ConfigurableAxis axisPtLog{"axisPtLog", {VARIABLE_WIDTH, 0.0f, 0.001f, 0.00104713f, 0.00109648f, 0.00114815f, 0.00120226f, 0.00125893f, 0.00131826f, 0.00138038f, 0.00144544f, 0.00151356f, 0.00158489f, 0.00165959f, 0.0017378f, 0.0018197f, 0.00190546f, 0.00199526f, 0.0020893f, 0.00218776f, 0.00229087f, 0.00239883f, 0.00251189f, 0.00263027f, 0.00275423f, 0.00288403f, 0.00301995f, 0.00316228f, 0.00331131f, 0.00346737f, 0.00363078f, 0.00380189f, 0.00398107f, 0.00416869f, 0.00436516f, 0.00457088f, 0.0047863f, 0.00501187f, 0.00524807f, 0.00549541f, 0.0057544f, 0.0060256f, 0.00630957f, 0.00660693f, 0.00691831f, 0.00724436f, 0.00758578f, 0.00794328f, 0.00831764f, 0.00870964f, 0.00912011f, 0.00954993f, 0.01f, 0.0104713f, 0.0109648f, 0.0114815f, 0.0120226f, 0.0125893f, 0.0131826f, 0.0138038f, 0.0144544f, 0.0151356f, 0.0158489f, 0.0165959f, 0.017378f, 0.018197f, 0.0190546f, 0.0199526f, 0.020893f, 0.0218776f, 0.0229087f, 0.0239883f, 0.0251189f, 0.0263027f, 0.0275423f, 0.0288403f, 0.0301995f, 0.0316228f, 0.0331131f, 0.0346737f, 0.0363078f, 0.0380189f, 0.0398107f, 0.0416869f, 0.0436516f, 0.0457088f, 0.047863f, 0.0501187f, 0.0524807f, 0.0549541f, 0.057544f, 0.060256f, 0.0630957f, 0.0660693f, 0.0691831f, 0.0724436f, 0.0758578f, 0.0794328f, 0.0831764f, 0.0870964f, 0.0912011f, 0.0954993f, 0.1f, 0.104713f, 0.109648f, 0.114815f, 0.120226f, 0.125893f, 0.131826f, 0.138038f, 0.144544f, 0.151356f, 0.158489f, 0.165959f, 0.17378f, 0.18197f, 0.190546f, 0.199526f, 0.20893f, 0.218776f, 0.229087f, 0.239883f, 0.251189f, 0.263027f, 0.275423f, 0.288403f, 0.301995f, 0.316228f, 0.331131f, 0.346737f, 0.363078f, 0.380189f, 0.398107f, 0.416869f, 0.436516f, 0.457088f, 0.47863f, 0.501187f, 0.524807f, 0.549541f, 0.57544f, 0.60256f, 0.630957f, 0.660693f, 0.691831f, 0.724436f, 0.758578f, 0.794328f, 0.831764f, 0.870964f, 0.912011f, 0.954993f, 1.0f, 1.04713f, 1.09648f, 1.14815f, 1.20226f, 1.25893f, 1.31826f, 1.38038f, 1.44544f, 1.51356f, 1.58489f, 1.65959f, 1.7378f, 1.8197f, 1.90546f, 1.99526f, 2.0893f, 2.18776f, 2.29087f, 2.39883f, 2.51189f, 2.63027f, 2.75423f, 2.88403f, 3.01995f, 3.16228f, 3.31131f, 3.46737f, 3.63078f, 3.80189f, 3.98107f, 4.16869f, 4.36516f, 4.57088f, 4.7863f, 5.01187f, 5.24807f, 5.49541f, 5.7544f, 6.0256f, 6.30957f, 6.60693f, 6.91831f, 7.24436f, 7.58578f, 7.94328f, 8.31764f, 8.70964f, 9.12011f, 9.54993f, 10.0f}, "pt axis for QA histograms"}; } axes; - Partition trueElectrons = aod::mcparticle::pdgCode == static_cast(PDG_t::kElectron); - Partition trueMuons = aod::mcparticle::pdgCode == static_cast(PDG_t::kMuonMinus); - Partition truePions = aod::mcparticle::pdgCode == static_cast(PDG_t::kPiPlus); - Partition trueKaons = aod::mcparticle::pdgCode == static_cast(PDG_t::kKMinus); - Partition trueProtons = aod::mcparticle::pdgCode == static_cast(PDG_t::kProton); - Partition trueK0Short = aod::mcparticle::pdgCode == static_cast(PDG_t::kK0Short); - Partition trueLambdas = aod::mcparticle::pdgCode == static_cast(PDG_t::kLambda0); - Partition trueXiMinus = aod::mcparticle::pdgCode == static_cast(PDG_t::kXiMinus); + Partition trueElectrons = aod::mcparticle::pdgCode == static_cast(PDG_t::kElectron); + Partition trueMuons = aod::mcparticle::pdgCode == static_cast(PDG_t::kMuonMinus); + Partition truePions = aod::mcparticle::pdgCode == static_cast(PDG_t::kPiPlus); + Partition trueKaons = aod::mcparticle::pdgCode == static_cast(PDG_t::kKMinus); + Partition trueProtons = aod::mcparticle::pdgCode == static_cast(PDG_t::kProton); + Partition trueK0Short = aod::mcparticle::pdgCode == static_cast(PDG_t::kK0Short); + Partition trueLambdas = aod::mcparticle::pdgCode == static_cast(PDG_t::kLambda0); + Partition trueXiMinus = aod::mcparticle::pdgCode == static_cast(PDG_t::kXiMinus); static constexpr size_t NCascadeDaughters = 2; static constexpr size_t NV0Daughters = 2; From 541325cf236d7e3128eb4e06a320d0f869fd1cfb Mon Sep 17 00:00:00 2001 From: jesgum Date: Wed, 27 May 2026 11:19:42 +0200 Subject: [PATCH 02/12] Fix compilation issues --- ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx index f79f78c778e..dc5b6f8cecc 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx @@ -71,7 +71,7 @@ static const std::vector pdgCodes{PDG_t::kK0Short, namespace o2::aod { O2ORIGIN("TMP"); } struct OnTheFlyDecayer { - Produces tableMcCollisions; + Produces tableMcCollisions; Produces tableMcParticles; o2::upgrade::Decayer decayer; @@ -168,7 +168,7 @@ struct OnTheFlyDecayer { decayParticles(stop, stop + ndau); } - void process(aod::McCollisions_001/*From>*/ const& mcCollisions, aod::McParticles_001From> const& mcParticles) + void process(aod::McCollisions_001From> const& mcCollisions, aod::McParticles_001From> const& mcParticles) { for (const auto& collision : mcCollisions) { allParticles.clear(); From 35869b27dc0e8a1c87bfb7449cfc46839e9c0f7d Mon Sep 17 00:00:00 2001 From: jesgum Date: Wed, 27 May 2026 11:39:17 +0200 Subject: [PATCH 03/12] Back to McParticles: alice3DecayerQa.cxx --- ALICE3/Tasks/alice3DecayerQa.cxx | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/ALICE3/Tasks/alice3DecayerQa.cxx b/ALICE3/Tasks/alice3DecayerQa.cxx index d4d41a8ae7e..11c45694c09 100644 --- a/ALICE3/Tasks/alice3DecayerQa.cxx +++ b/ALICE3/Tasks/alice3DecayerQa.cxx @@ -17,8 +17,6 @@ /// \since Dec 23, 2025 /// -#include "ALICE3/DataModel/OTFMCParticle.h" - #include #include #include @@ -46,7 +44,7 @@ struct Alice3DecayerQa { ConfigurableAxis axisCollisionId{"axisCollisionId", {1000, 0, 999}, "CollisionId axis for QA histograms"}; ConfigurableAxis axisPdgCode{"axisPdgCode", {1000, 0, 999}, "PdgCode axis for QA histograms"}; ConfigurableAxis axisStatusCode{"axisStatusCode", {1000, 0, 999}, "StatusCode axis for QA histograms"}; - ConfigurableAxis axisFlags{"axisFlags", {10, 0, 9}, "Flags axis for QA histograms"}; + ConfigurableAxis axisFlags{"axisFlags", {256, 0, 255}, "Flags axis for QA histograms"}; ConfigurableAxis axisMothersIds{"axisMothersIds", {1000, 0, 999}, "MothersIds axis for QA histograms"}; ConfigurableAxis axisDaughtersIds{"axisDaughtersIds", {1000, 0, 999}, "DaughtersIds axis for QA histograms"}; ConfigurableAxis axisWeight{"axisWeight", {2, 0, 1}, "Weight axis for QA histograms"}; @@ -101,8 +99,6 @@ struct Alice3DecayerQa { histos.add("MCWithDau/hPhi", "hPhi", kTH1D, {axes.axisPhi}); histos.add("MCWithDau/hEta", "hEta", kTH1D, {axes.axisEta}); histos.add("MCWithDau/hRapidity", "hRapidity", kTH1D, {axes.axisRapidity}); - histos.add("MCWithDau/hIsAlive", "hIsAlive", kTH1D, {axes.axisIsAlive}); - histos.add("MCWithDau/hIsPrimary", "hIsPrimary", kTH1D, {axes.axisIsPrimary}); histos.add("MCWithDau/hPx", "hPx", kTH1D, {axes.axisPt}); histos.add("MCWithDau/hPy", "hPy", kTH1D, {axes.axisPt}); histos.add("MCWithDau/hPz", "hPz", kTH1D, {axes.axisPt}); @@ -134,7 +130,7 @@ struct Alice3DecayerQa { hCheckHasXiMinusDecayed->GetXaxis()->SetBinLabel(2, "Yes"); } - void process(const aod::McCollision& collision, const aod::McPartWithDaus& particles) + void process(const aod::McCollision& collision, const aod::McParticles& particles) { // Group with collision auto trueElectronsGrouped = trueElectrons->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); @@ -173,6 +169,7 @@ struct Alice3DecayerQa { // K0S -> pi+ pi- const bool k0sDecay = (dau0.pdgCode() == PDG_t::kPiPlus && dau1.pdgCode() == PDG_t::kPiMinus) || (dau0.pdgCode() == PDG_t::kPiMinus && dau1.pdgCode() == PDG_t::kPiPlus); + if (k0sDecay) { auto& positive = dau0.pdgCode() == PDG_t::kPiPlus ? dau0 : dau1; auto& negative = dau0.pdgCode() == PDG_t::kPiPlus ? dau1 : dau0; @@ -196,6 +193,7 @@ struct Alice3DecayerQa { // Lambda -> p pi- const bool lambdaDecay = (dau0.pdgCode() == PDG_t::kProton && dau1.pdgCode() == PDG_t::kPiMinus) || (dau0.pdgCode() == PDG_t::kPiMinus && dau1.pdgCode() == PDG_t::kProton); + if (lambdaDecay) { auto& positive = dau0.pdgCode() == PDG_t::kProton ? dau0 : dau1; auto& negative = dau0.pdgCode() == PDG_t::kProton ? dau1 : dau0; @@ -219,6 +217,7 @@ struct Alice3DecayerQa { // Xi- -> Lambda pi- const bool xiDecay = (dau0.pdgCode() == PDG_t::kLambda0 && dau1.pdgCode() == PDG_t::kPiMinus) || (dau0.pdgCode() == PDG_t::kPiMinus && dau1.pdgCode() == PDG_t::kLambda0); + if (xiDecay) { auto& v0 = dau0.pdgCode() == PDG_t::kLambda0 ? dau0 : dau1; auto& bachelor = dau0.pdgCode() == PDG_t::kLambda0 ? dau1 : dau0; @@ -261,8 +260,6 @@ struct Alice3DecayerQa { histos.fill(HIST("MCWithDau/hPhi"), particle.phi()); histos.fill(HIST("MCWithDau/hEta"), particle.eta()); histos.fill(HIST("MCWithDau/hRapidity"), particle.y()); - histos.fill(HIST("MCWithDau/hIsAlive"), particle.isAlive()); - histos.fill(HIST("MCWithDau/hIsPrimary"), particle.isPrimary()); histos.fill(HIST("MCWithDau/hPx"), particle.px()); histos.fill(HIST("MCWithDau/hPy"), particle.py()); histos.fill(HIST("MCWithDau/hPz"), particle.pz()); From 66611ba13320470f6ebb32da1d8ef58dac469e42 Mon Sep 17 00:00:00 2001 From: jesgum Date: Wed, 27 May 2026 11:55:52 +0200 Subject: [PATCH 04/12] Add McParticleExtension spawner to decayer --- ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx index dc5b6f8cecc..0b7c22c02ec 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx @@ -212,7 +212,12 @@ struct OnTheFlyDecayer { } }; +struct OnTheFlyDecayerExtensionSpawner { + Spawns spawnMcParticlesExtensions; + void init(InitContext const&) {} +}; + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc)}; } From 26a60d133110f97d9b391027c6a834384e0af2e1 Mon Sep 17 00:00:00 2001 From: jesgum Date: Wed, 27 May 2026 14:25:41 +0200 Subject: [PATCH 05/12] otf tracker deprecate McPartsWithDau --- ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx | 7 +- ALICE3/TableProducer/OTF/onTheFlyTracker.cxx | 9 +- ALICE3/Tasks/alice3DecayerQa.cxx | 101 ++++++++++--------- 3 files changed, 59 insertions(+), 58 deletions(-) diff --git a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx index 0b7c22c02ec..3c8b6e922f4 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx @@ -172,6 +172,8 @@ struct OnTheFlyDecayer { { for (const auto& collision : mcCollisions) { allParticles.clear(); + + // Reproduce collision table to have AOD origin mCollisionId = collision.globalIndex(); tableMcCollisions(collision.bcId(), collision.generatorsID(), @@ -214,10 +216,11 @@ struct OnTheFlyDecayer { struct OnTheFlyDecayerExtensionSpawner { Spawns spawnMcParticlesExtensions; - void init(InitContext const&) {} + void init(o2::framework::InitContext&) {} }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; } diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx index 0ba1c3e57e0..78f6772fbe0 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -30,7 +30,6 @@ #include "ALICE3/Core/OTFParticle.h" #include "ALICE3/Core/TrackUtilities.h" #include "ALICE3/DataModel/OTFCollision.h" -#include "ALICE3/DataModel/OTFMCParticle.h" #include "ALICE3/DataModel/OTFStrangeness.h" #include "ALICE3/DataModel/collisionAlice3.h" #include "ALICE3/DataModel/tracksAlice3.h" @@ -137,7 +136,6 @@ struct OnTheFlyTracker { Produces tableStoredTracksCov; Produces tableTracksCovExtension; Produces tableMcTrackLabels; - Produces tableMcTrackWithDauLabels; Produces tableTracksDCA; Produces tableTracksDCACov; Produces tableCollisionsAlice3; @@ -1731,7 +1729,6 @@ struct OnTheFlyTracker { trackParCov.getSigmaTgl2(), trackParCov.getSigma1PtY(), trackParCov.getSigma1PtZ(), trackParCov.getSigma1PtSnp(), trackParCov.getSigma1PtTgl(), trackParCov.getSigma1Pt2()); tableMcTrackLabels(trackParCov.mcLabel, 0); - tableMcTrackWithDauLabels(trackParCov.mcLabel, 0); tableTracksExtraA3(trackParCov.nSiliconHits, trackParCov.nTPCHits, trackParCov.trackType); // populate extra tables if required to do so @@ -1933,7 +1930,7 @@ struct OnTheFlyTracker { } } - void processConfigurationDev(aod::McCollision const& mcCollision, aod::McPartWithDaus const& mcParticles, const int icfg) + void processConfigurationDev(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const int icfg) { const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; tracksAlice3.clear(); @@ -2000,7 +1997,7 @@ struct OnTheFlyTracker { bool reconstructed = false; int nTrkHits = 0; - if (enablePrimarySmearing && mcParticle.isPrimary()) { + if (enablePrimarySmearing && mcParticle.isPhysicalPrimary()) { o2::upgrade::convertMCParticleToO2Track(mcParticle, trackParCov, pdgDB); reconstructed = mSmearer[icfg]->smearTrack(trackParCov, mcParticle.pdgCode(), dNdEta); nTrkHits = fastTrackerSettings.minSiliconHits; @@ -2074,7 +2071,7 @@ struct OnTheFlyTracker { fillTracksInfo(ghostTracksAlice3, primaryVertex, icfg); } - void processDecayer(aod::McCollision const& mcCollision, aod::McPartWithDaus const& mcParticles) + void processDecayer(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles) { for (size_t icfg = 0; icfg < mSmearer.size(); ++icfg) { processConfigurationDev(mcCollision, mcParticles, static_cast(icfg)); diff --git a/ALICE3/Tasks/alice3DecayerQa.cxx b/ALICE3/Tasks/alice3DecayerQa.cxx index 11c45694c09..7323e7f380b 100644 --- a/ALICE3/Tasks/alice3DecayerQa.cxx +++ b/ALICE3/Tasks/alice3DecayerQa.cxx @@ -80,31 +80,31 @@ struct Alice3DecayerQa { void init(o2::framework::InitContext&) { // QA with Table entries - histos.add("MCWithDau/hElPt", "hElPt", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hMuPt", "hMuPt", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hPiPt", "hPiPt", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hKaPt", "hKaPt", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hPrPt", "hPrPt", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hCollisionId", "hCollisionId", kTH1D, {axes.axisCollisionId}); - histos.add("MCWithDau/hPdgCode", "hPdgCode", kTH1D, {axes.axisPdgCode}); - histos.add("MCWithDau/hStatusCode", "hStatusCode", kTH1D, {axes.axisStatusCode}); - histos.add("MCWithDau/hFlags", "hFlags", kTH1D, {axes.axisFlags}); - histos.add("MCWithDau/hMothersIds", "hMothersIds", kTH1D, {axes.axisMothersIds}); - histos.add("MCWithDau/hDaughtersIds", "hDaughtersIds", kTH1D, {axes.axisDaughtersIds}); - histos.add("MCWithDau/hWeight", "hWeight", kTH1D, {axes.axisWeight}); - histos.add("MCWithDau/hVx", "hVx", kTH1D, {axes.axisPos}); - histos.add("MCWithDau/hVy", "hVy", kTH1D, {axes.axisPos}); - histos.add("MCWithDau/hVz", "hVz", kTH1D, {axes.axisPos}); - histos.add("MCWithDau/hVt", "hVt", kTH1D, {axes.axisPos}); - histos.add("MCWithDau/hPhi", "hPhi", kTH1D, {axes.axisPhi}); - histos.add("MCWithDau/hEta", "hEta", kTH1D, {axes.axisEta}); - histos.add("MCWithDau/hRapidity", "hRapidity", kTH1D, {axes.axisRapidity}); - histos.add("MCWithDau/hPx", "hPx", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hPy", "hPy", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hPz", "hPz", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hPt", "hPt", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hP", "hP", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hE", "hE", kTH1D, {axes.axisPt}); + histos.add("McParticle/hElPt", "hElPt", kTH1D, {axes.axisPt}); + histos.add("McParticle/hMuPt", "hMuPt", kTH1D, {axes.axisPt}); + histos.add("McParticle/hPiPt", "hPiPt", kTH1D, {axes.axisPt}); + histos.add("McParticle/hKaPt", "hKaPt", kTH1D, {axes.axisPt}); + histos.add("McParticle/hPrPt", "hPrPt", kTH1D, {axes.axisPt}); + histos.add("McParticle/hCollisionId", "hCollisionId", kTH1D, {axes.axisCollisionId}); + histos.add("McParticle/hPdgCode", "hPdgCode", kTH1D, {axes.axisPdgCode}); + histos.add("McParticle/hStatusCode", "hStatusCode", kTH1D, {axes.axisStatusCode}); + histos.add("McParticle/hFlags", "hFlags", kTH1D, {axes.axisFlags}); + histos.add("McParticle/hMothersIds", "hMothersIds", kTH1D, {axes.axisMothersIds}); + histos.add("McParticle/hDaughtersIds", "hDaughtersIds", kTH1D, {axes.axisDaughtersIds}); + histos.add("McParticle/hWeight", "hWeight", kTH1D, {axes.axisWeight}); + histos.add("McParticle/hVx", "hVx", kTH1D, {axes.axisPos}); + histos.add("McParticle/hVy", "hVy", kTH1D, {axes.axisPos}); + histos.add("McParticle/hVz", "hVz", kTH1D, {axes.axisPos}); + histos.add("McParticle/hVt", "hVt", kTH1D, {axes.axisPos}); + histos.add("McParticle/hPhi", "hPhi", kTH1D, {axes.axisPhi}); + histos.add("McParticle/hEta", "hEta", kTH1D, {axes.axisEta}); + histos.add("McParticle/hRapidity", "hRapidity", kTH1D, {axes.axisRapidity}); + histos.add("McParticle/hPx", "hPx", kTH1D, {axes.axisPt}); + histos.add("McParticle/hPy", "hPy", kTH1D, {axes.axisPt}); + histos.add("McParticle/hPz", "hPz", kTH1D, {axes.axisPt}); + histos.add("McParticle/hPt", "hPt", kTH1D, {axes.axisPt}); + histos.add("McParticle/hP", "hP", kTH1D, {axes.axisPt}); + histos.add("McParticle/hE", "hE", kTH1D, {axes.axisPt}); // QA with daughters from Decayer histos.add("K0S/hGeneratedPt", "hGeneratedPt;#it{p}_{T} (GeV/#it{c})", kTH1D, {axes.axisPt}); @@ -132,6 +132,7 @@ struct Alice3DecayerQa { void process(const aod::McCollision& collision, const aod::McParticles& particles) { + LOG(info) << particles.size(); // Group with collision auto trueElectronsGrouped = trueElectrons->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); auto trueMuonsGrouped = trueMuons->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); @@ -143,19 +144,19 @@ struct Alice3DecayerQa { auto trueXiMinusGrouped = trueXiMinus->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); for (const auto& particle : trueElectronsGrouped) { - histos.fill(HIST("MCWithDau/hElPt"), particle.pt()); + histos.fill(HIST("McParticle/hElPt"), particle.pt()); } for (const auto& particle : trueMuonsGrouped) { - histos.fill(HIST("MCWithDau/hMuPt"), particle.pt()); + histos.fill(HIST("McParticle/hMuPt"), particle.pt()); } for (const auto& particle : truePionsGrouped) { - histos.fill(HIST("MCWithDau/hPiPt"), particle.pt()); + histos.fill(HIST("McParticle/hPiPt"), particle.pt()); } for (const auto& particle : trueKaonsGrouped) { - histos.fill(HIST("MCWithDau/hKaPt"), particle.pt()); + histos.fill(HIST("McParticle/hKaPt"), particle.pt()); } for (const auto& particle : trueProtonsGrouped) { - histos.fill(HIST("MCWithDau/hPrPt"), particle.pt()); + histos.fill(HIST("McParticle/hPrPt"), particle.pt()); } for (const auto& particle : trueK0ShortGrouped) { histos.fill(HIST("K0S/hGeneratedPt"), particle.pt()); @@ -248,29 +249,29 @@ struct Alice3DecayerQa { } for (const auto& particle : particles) { - histos.fill(HIST("MCWithDau/hCollisionId"), particle.mcCollisionId()); - histos.fill(HIST("MCWithDau/hPdgCode"), particle.pdgCode()); - histos.fill(HIST("MCWithDau/hStatusCode"), particle.statusCode()); - histos.fill(HIST("MCWithDau/hFlags"), particle.flags()); - histos.fill(HIST("MCWithDau/hWeight"), particle.weight()); - histos.fill(HIST("MCWithDau/hVx"), particle.vx()); - histos.fill(HIST("MCWithDau/hVy"), particle.vy()); - histos.fill(HIST("MCWithDau/hVz"), particle.vz()); - histos.fill(HIST("MCWithDau/hVt"), particle.vt()); - histos.fill(HIST("MCWithDau/hPhi"), particle.phi()); - histos.fill(HIST("MCWithDau/hEta"), particle.eta()); - histos.fill(HIST("MCWithDau/hRapidity"), particle.y()); - histos.fill(HIST("MCWithDau/hPx"), particle.px()); - histos.fill(HIST("MCWithDau/hPy"), particle.py()); - histos.fill(HIST("MCWithDau/hPz"), particle.pz()); - histos.fill(HIST("MCWithDau/hPt"), particle.pt()); - histos.fill(HIST("MCWithDau/hP"), particle.p()); - histos.fill(HIST("MCWithDau/hE"), particle.e()); + histos.fill(HIST("McParticle/hCollisionId"), particle.mcCollisionId()); + histos.fill(HIST("McParticle/hPdgCode"), particle.pdgCode()); + histos.fill(HIST("McParticle/hStatusCode"), particle.statusCode()); + histos.fill(HIST("McParticle/hFlags"), particle.flags()); + histos.fill(HIST("McParticle/hWeight"), particle.weight()); + histos.fill(HIST("McParticle/hVx"), particle.vx()); + histos.fill(HIST("McParticle/hVy"), particle.vy()); + histos.fill(HIST("McParticle/hVz"), particle.vz()); + histos.fill(HIST("McParticle/hVt"), particle.vt()); + histos.fill(HIST("McParticle/hPhi"), particle.phi()); + histos.fill(HIST("McParticle/hEta"), particle.eta()); + histos.fill(HIST("McParticle/hRapidity"), particle.y()); + histos.fill(HIST("McParticle/hPx"), particle.px()); + histos.fill(HIST("McParticle/hPy"), particle.py()); + histos.fill(HIST("McParticle/hPz"), particle.pz()); + histos.fill(HIST("McParticle/hPt"), particle.pt()); + histos.fill(HIST("McParticle/hP"), particle.p()); + histos.fill(HIST("McParticle/hE"), particle.e()); for (const auto& motherParticleId : particle.mothersIds()) { - histos.fill(HIST("MCWithDau/hMothersIds"), motherParticleId); + histos.fill(HIST("McParticle/hMothersIds"), motherParticleId); } for (const auto& dauParticleId : particle.daughtersIds()) { - histos.fill(HIST("MCWithDau/hDaughtersIds"), dauParticleId); + histos.fill(HIST("McParticle/hDaughtersIds"), dauParticleId); } } } From 5def4158f33153fb7f500cca6af9f4b1e11cf2e8 Mon Sep 17 00:00:00 2001 From: jesgum Date: Wed, 27 May 2026 15:09:45 +0200 Subject: [PATCH 06/12] deprecate McPartWithDaus in a3 strangeness task --- .../TableProducer/alice3strangenessFinder.cxx | 60 +++++++------------ ALICE3/Tasks/alice3Strangeness.cxx | 3 +- 2 files changed, 23 insertions(+), 40 deletions(-) diff --git a/ALICE3/TableProducer/alice3strangenessFinder.cxx b/ALICE3/TableProducer/alice3strangenessFinder.cxx index e96db585c25..c180a6ea907 100644 --- a/ALICE3/TableProducer/alice3strangenessFinder.cxx +++ b/ALICE3/TableProducer/alice3strangenessFinder.cxx @@ -22,7 +22,6 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" #include "ALICE3/Core/TrackUtilities.h" -#include "ALICE3/DataModel/OTFMCParticle.h" #include "ALICE3/DataModel/OTFPIDTrk.h" #include "ALICE3/DataModel/OTFRICH.h" #include "ALICE3/DataModel/OTFStrangeness.h" @@ -66,7 +65,7 @@ using namespace o2::constants::physics; using Alice3TracksWPid = soa::Join; using Alice3TracksACTS = soa::Join; -using Alice3TracksOTF = soa::Join; +using Alice3TracksOTF = soa::Join; using Alice3MCParticles = soa::Join; struct Alice3strangenessFinder { @@ -270,34 +269,21 @@ struct Alice3strangenessFinder { template bool checkSameMother(TTrackType const& track1, TTrackType const& track2) { - // MC label points to McPartWithDaus - if constexpr (requires { track1.has_mcPartWithDau(); }) { - if (!track1.has_mcPartWithDau() || !track2.has_mcPartWithDau()) { - return false; - } - auto mcParticle1 = track1.template mcPartWithDau_as(); - auto mcParticle2 = track2.template mcPartWithDau_as(); - if (mcParticle1.mothersIds().empty() || mcParticle2.mothersIds().empty()) { - return false; - } - return mcParticle1.mothersIds()[0] == mcParticle2.mothersIds()[0]; - } else { // MC label points directly to aod::McParticles - bool returnValue = false; - if (track1.has_mcParticle() && track2.has_mcParticle()) { - auto mcParticle1 = track1.template mcParticle_as(); - auto mcParticle2 = track2.template mcParticle_as(); - if (mcParticle1.has_mothers() && mcParticle2.has_mothers()) { - for (const auto& m1 : mcParticle1.template mothers_as()) { - for (const auto& m2 : mcParticle2.template mothers_as()) { - if (m1.globalIndex() == m2.globalIndex()) { - returnValue = true; - } + bool returnValue = false; + if (track1.has_mcParticle() && track2.has_mcParticle()) { + auto mcParticle1 = track1.template mcParticle_as(); + auto mcParticle2 = track2.template mcParticle_as(); + if (mcParticle1.has_mothers() && mcParticle2.has_mothers()) { + for (const auto& m1 : mcParticle1.template mothers_as()) { + for (const auto& m2 : mcParticle2.template mothers_as()) { + if (m1.globalIndex() == m2.globalIndex()) { + returnValue = true; } } } } - return returnValue; } + return returnValue; } template @@ -465,18 +451,16 @@ struct Alice3strangenessFinder { } // OTF: pdg code from mcParticle table - if constexpr (requires { posTrack.has_mcPartWithDau(); }) { - if (!posTrack.has_mcPartWithDau() && !negTrack.has_mcPartWithDau()) { - continue; - } - auto mcParticlePos = posTrack.template mcPartWithDau_as(); - auto mcParticleNeg = negTrack.template mcPartWithDau_as(); - if ((mcParticlePos.pdgCode() != kPiPlus && mcParticleNeg.pdgCode() != kPiMinus) && isK0Gun) { - continue; - } - if ((mcParticlePos.pdgCode() != kProton && mcParticleNeg.pdgCode() != kPiMinus) && isLambdaGun) { - continue; - } + if (!posTrack.has_mcParticle() && !negTrack.has_mcParticle()) { + continue; + } + auto mcParticlePos = posTrack.template mcParticle_as(); + auto mcParticleNeg = negTrack.template mcParticle_as(); + if ((mcParticlePos.pdgCode() != kPiPlus && mcParticleNeg.pdgCode() != kPiMinus) && isK0Gun) { + continue; + } + if ((mcParticlePos.pdgCode() != kProton && mcParticleNeg.pdgCode() != kPiMinus) && isLambdaGun) { + continue; } histos.fill(HIST("hV0Building"), 2.0); @@ -682,7 +666,7 @@ struct Alice3strangenessFinder { processFindV0CandidateNoPid(collision, negTracksGrouped, posTracksGrouped, bachTracksGrouped); } - void processFindV0CandidateOTF(aod::Collision const& collision, Alice3TracksOTF const&, aod::McPartWithDaus const&) + void processFindV0CandidateOTF(aod::Collision const& collision, Alice3TracksOTF const&, aod::McParticles const&) { auto negTracksGrouped = negativeSecondaryTracksOTF->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto posTracksGrouped = positiveSecondaryTracksOTF->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); diff --git a/ALICE3/Tasks/alice3Strangeness.cxx b/ALICE3/Tasks/alice3Strangeness.cxx index 7527db49495..499624cd6bf 100644 --- a/ALICE3/Tasks/alice3Strangeness.cxx +++ b/ALICE3/Tasks/alice3Strangeness.cxx @@ -20,7 +20,6 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" #include "ALICE3/DataModel/OTFCollision.h" -#include "ALICE3/DataModel/OTFMCParticle.h" #include "ALICE3/DataModel/OTFStrangeness.h" #include "ALICE3/DataModel/tracksAlice3.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -50,7 +49,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::constants::math; -using Alice3Tracks = soa::Join; +using Alice3Tracks = soa::Join; using FullV0Candidates = soa::Join; using FullCascadeCandidates = soa::Join; using FullCollisions = soa::Join; From 16fa0b224d3fd2497760283e2875464fbecbd794 Mon Sep 17 00:00:00 2001 From: jesgum Date: Wed, 27 May 2026 15:11:35 +0200 Subject: [PATCH 07/12] fully deprecate McPartWithDaus --- ALICE3/DataModel/OTFMCParticle.h | 94 -------------------- ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx | 1 - 2 files changed, 95 deletions(-) delete mode 100644 ALICE3/DataModel/OTFMCParticle.h diff --git a/ALICE3/DataModel/OTFMCParticle.h b/ALICE3/DataModel/OTFMCParticle.h deleted file mode 100644 index 56a1400a2e9..00000000000 --- a/ALICE3/DataModel/OTFMCParticle.h +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// -/// \file OTFMCParticle.h -/// \author Jesper Karlsson Gumprecht -/// \since 16/12/2025 -/// \brief Redefinition of the mcparticles table specifically for the fast sim -/// - -#ifndef ALICE3_DATAMODEL_OTFMCPARTICLE_H_ -#define ALICE3_DATAMODEL_OTFMCPARTICLE_H_ - -#include - -#include - -namespace o2::aod -{ - -namespace otfmcparticle -{ -DECLARE_SOA_COLUMN(Phi, phi, float); -DECLARE_SOA_COLUMN(Eta, eta, float); -DECLARE_SOA_COLUMN(Pt, pt, float); -DECLARE_SOA_COLUMN(P, p, float); -DECLARE_SOA_COLUMN(Y, y, float); -DECLARE_SOA_COLUMN(IsAlive, isAlive, bool); -DECLARE_SOA_COLUMN(IsPrimary, isPrimary, bool); - -DECLARE_SOA_SELF_INDEX_COLUMN_FULL(Mother0, mother0, int, "McPartsWithDau_Mother0"); //! Track index of the first mother -DECLARE_SOA_SELF_INDEX_COLUMN_FULL(Mother1, mother1, int, "McPartsWithDau_Mother1"); //! Track index of the last mother -DECLARE_SOA_SELF_INDEX_COLUMN_FULL(Daughter0, daughter0, int, "McPartsWithDau_Daughter0"); //! Track index of the first daugther -DECLARE_SOA_SELF_INDEX_COLUMN_FULL(Daughter1, daughter1, int, "McPartsWithDau_Daughter1"); //! Track index of the last daugther -DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(Mothers, mothers); //! Mother tracks (possible empty) array. Iterate over mcParticle.mothers_as()) -DECLARE_SOA_SELF_SLICE_INDEX_COLUMN(Daughters, daughters); //! Daughter tracks (possibly empty) slice. Check for non-zero with mcParticle.has_daughters(). Iterate over mcParticle.daughters_as()) -} // namespace otfmcparticle - -DECLARE_SOA_TABLE_FULL(McPartWithDaus, "McPartWithDaus", "AOD", "MCPARTSWITHDAU", - o2::soa::Index<>, - mcparticle::McCollisionId, - mcparticle::PdgCode, - mcparticle::StatusCode, - mcparticle::Flags, - otfmcparticle::MothersIds, - otfmcparticle::DaughtersIdSlice, - mcparticle::Weight, - mcparticle::Px, - mcparticle::Py, - mcparticle::Pz, - mcparticle::E, - mcparticle::Vx, - mcparticle::Vy, - mcparticle::Vz, - mcparticle::Vt, - otfmcparticle::Phi, - otfmcparticle::Eta, - otfmcparticle::Pt, - otfmcparticle::P, - otfmcparticle::Y, - otfmcparticle::IsAlive, - otfmcparticle::IsPrimary, - mcparticle::PVector, - mcparticle::ProducedByGenerator, - mcparticle::FromBackgroundEvent, - mcparticle::GetGenStatusCode, - mcparticle::GetHepMCStatusCode, - mcparticle::GetProcess, - mcparticle::IsPhysicalPrimary); - -using McPartWithDau = McPartWithDaus::iterator; - -namespace otfmctracklable -{ -DECLARE_SOA_INDEX_COLUMN(McPartWithDau, mcPartWithDau); //! MC particle -DECLARE_SOA_COLUMN(McMask, mcMask, uint16_t); //! Bit mask to indicate detector mismatches (bit ON means mismatch). Bit 0-6: mismatch at ITS layer. Bit 12: ITSAB tracklet mismatch. Bit 13: ITS-TPC mismatch. Bit 14: isNoise == True (global track), Bit 15: isFake == True (global track) -} // namespace otfmctracklable - -DECLARE_SOA_TABLE(McTrackWithDauLabels, "AOD", "MCTRACKWithDAULABEL", //! Table joined to the track table containing the MC index - otfmctracklable::McPartWithDauId, otfmctracklable::McMask); - -using McTrackWithDauLabel = McTrackWithDauLabels::iterator; - -} // namespace o2::aod - -#endif // ALICE3_DATAMODEL_OTFMCPARTICLE_H_ diff --git a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx index 3c8b6e922f4..128b60e0b24 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx @@ -18,7 +18,6 @@ #include "ALICE3/Core/Decayer.h" #include "ALICE3/Core/OTFParticle.h" #include "ALICE3/Core/TrackUtilities.h" -#include "ALICE3/DataModel/OTFMCParticle.h" #include #include From 8a8426f3d3fb44bcd629883a01053925f754712f Mon Sep 17 00:00:00 2001 From: jesgum Date: Thu, 28 May 2026 14:13:03 +0200 Subject: [PATCH 08/12] add extra decayer information to otfParticle --- ALICE3/Core/Decayer.h | 1 + ALICE3/Core/OTFParticle.h | 49 +++++++++++++------ ALICE3/DataModel/tracksAlice3.h | 4 ++ ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx | 15 +++--- ALICE3/TableProducer/OTF/onTheFlyTracker.cxx | 9 ++-- .../TableProducer/alice3strangenessFinder.cxx | 2 +- 6 files changed, 55 insertions(+), 25 deletions(-) diff --git a/ALICE3/Core/Decayer.h b/ALICE3/Core/Decayer.h index 51296ffe67d..52ca0a75adb 100644 --- a/ALICE3/Core/Decayer.h +++ b/ALICE3/Core/Decayer.h @@ -126,6 +126,7 @@ class Decayer particle.setPDG(pdgCodesDaughters[i]); particle.setVxVyVz(mVx, mVy, mVz); particle.setPxPyPzE(dau.Px(), dau.Py(), dau.Pz(), dau.E()); + particle.setBitOn(o2::upgrade::DecayerBits::ProducedByDecayer); decayProducts.push_back(particle); } diff --git a/ALICE3/Core/OTFParticle.h b/ALICE3/Core/OTFParticle.h index c66fc73665f..73b5183ffed 100644 --- a/ALICE3/Core/OTFParticle.h +++ b/ALICE3/Core/OTFParticle.h @@ -21,13 +21,17 @@ #include #include +#include #include #include #include namespace o2::upgrade { -static constexpr uint8_t ProducedByDecayer = 0xFF; + +enum class DecayerBits { ProducedByDecayer = 0, + IsPrimary, + IsAlive }; class OTFParticle { @@ -48,20 +52,29 @@ class OTFParticle mVy = particle.vy(); mVz = particle.vz(); mVt = particle.vt(); + mFlag = particle.flags(); + mStatusCode = particle.statusCode(); mIsFromMcParticles = true; if (particle.has_mothers()) { mIndicesMother = {particle.mothersIds().front(), particle.mothersIds().back()}; } + if constexpr ( requires { particle.decayerBits(); } ) { + mBits = particle.decayerBits(); + } else { + // If we are here, we created particle in the standard workflow -- without secondaries + // Then we should set all particles as physical primaries accordingly + setBitOn(DecayerBits::IsPrimary); + } } // Setters - void setIsAlive(const bool isAlive) { mIsAlive = isAlive; } void setIsPrimary(const bool isPrimary) { mIsPrimary = isPrimary; } void setCollisionId(const int collisionId) { mCollisionId = collisionId; } void setPDG(const int pdg) { mPdgCode = pdg; } void setIndicesMother(const int start, const int stop) { mIndicesMother = {start, stop}; } void setIndicesDaughter(const int start, const int stop) { mIndicesDaughter = {start, stop}; } void setProductionTime(const float vt) { mVt = vt; } + void setFlags(uint8_t flag) { mFlag = flag; } void setVxVyVz(const float vx, const float vy, const float vz) { mVx = vx; @@ -88,16 +101,8 @@ class OTFParticle static constexpr float Weight = 1.f; return Weight; } - uint8_t flags() const - { - static constexpr uint8_t Flags = 1; - return Flags; // todo - } - int statusCode() const - { - static constexpr int StatusCode = 1; - return StatusCode; // todo - } + uint8_t flags() const { return mFlag; } + int statusCode() const { return mStatusCode; } float vx() const { return mVx; } float vy() const { return mVy; } float vz() const { return mVz; } @@ -113,7 +118,8 @@ class OTFParticle float phi() const { return o2::constants::math::PI + std::atan2(-1.0f * py(), -1.0f * px()); } float eta() const { - // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1943 + // Conditionally defined to avoid FPEs + // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1959 static constexpr float Tolerance = 1e-7f; if ((p() - mPz) < Tolerance) { return (mPz < 0.0f) ? -100.0f : 100.0f; @@ -123,7 +129,8 @@ class OTFParticle } float y() const { - // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1922 + // Conditionally defined to avoid FPEs + // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1980 static constexpr float Tolerance = 1e-7f; if ((e() - mPz) < Tolerance) { return (mPz < 0.0f) ? -100.0f : 100.0f; @@ -152,6 +159,16 @@ class OTFParticle return (mGlobalIndex != -1); } + // Bits + bool checkBit(DecayerBits bit) const { return mBits.test(static_cast(bit)); } + void setBit(DecayerBits bit, bool value = true) { mBits.set(static_cast(bit), value); } + void setBitOn(DecayerBits bit) { mBits.set(static_cast(bit), true); } + void setBitOff(DecayerBits bit) { mBits.set(static_cast(bit), false); } + + std::bitset<8> getBits() const { return mBits; } + uint8_t getBitsValue() const { return static_cast(mBits.to_ulong()); } + void setBits(std::bitset<8> bits) { mBits = bits; } + private: int mPdgCode{}, mGlobalIndex{-1}; int mCollisionId{}; @@ -159,6 +176,10 @@ class OTFParticle float mPx{}, mPy{}, mPz{}, mE{}; bool mIsAlive{}, mIsFromMcParticles{false}; bool mIsPrimary{}; + + int mStatusCode{}; + uint8_t mFlag{}; + std::bitset<8> mBits{}; std::array mIndicesMother{-1, -1}, mIndicesDaughter{-1, -1}; }; diff --git a/ALICE3/DataModel/tracksAlice3.h b/ALICE3/DataModel/tracksAlice3.h index 374069de4cb..b6ccc587d91 100644 --- a/ALICE3/DataModel/tracksAlice3.h +++ b/ALICE3/DataModel/tracksAlice3.h @@ -50,11 +50,15 @@ namespace mcparticle_alice3 { DECLARE_SOA_COLUMN(NHits, nHits, int); //! number of silicon hits DECLARE_SOA_COLUMN(Charge, charge, float); //! particle charge +DECLARE_SOA_BITMAP_COLUMN(DecayerBits, decayerBits, 8); //! Bit mask for particle produced by the OTF decayer } // namespace mcparticle_alice3 DECLARE_SOA_TABLE(MCParticlesExtraA3, "AOD", "MCParticlesExtraA3", mcparticle_alice3::NHits, mcparticle_alice3::Charge); using MCParticleExtraA3 = MCParticlesExtraA3::iterator; + +DECLARE_SOA_TABLE(OTFDecayerBits, "AOD", "OTFDecayerBits", mcparticle_alice3::DecayerBits); + } // namespace o2::aod #endif // ALICE3_DATAMODEL_TRACKSALICE3_H_ diff --git a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx index 128b60e0b24..1de90499abe 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx @@ -17,6 +17,7 @@ #include "ALICE3/Core/Decayer.h" #include "ALICE3/Core/OTFParticle.h" +#include "ALICE3/DataModel/tracksAlice3.h" #include "ALICE3/Core/TrackUtilities.h" #include @@ -72,6 +73,7 @@ namespace o2::aod { O2ORIGIN("TMP"); } struct OnTheFlyDecayer { Produces tableMcCollisions; Produces tableMcParticles; + Produces tableOTFDecayerBits; o2::upgrade::Decayer decayer; Service pdgDB; @@ -122,15 +124,15 @@ struct OnTheFlyDecayer { for (int i = start; i < stop; i++) { o2::upgrade::OTFParticle& particle = allParticles[i]; if (particle.isFromMcParticles()) { - particle.setIsPrimary(true); - particle.setIsAlive(true); + particle.setBitOn(o2::upgrade::DecayerBits::IsPrimary); + particle.setBitOn(o2::upgrade::DecayerBits::IsAlive); } if (!canDecay(particle)) { continue; } - particle.setIsAlive(false); + particle.setBitOff(o2::upgrade::DecayerBits::IsAlive); std::vector decayStack = decayer.decayParticle(pdgDB, particle); const float decayRadius = decayer.getDecayRadius(); const float trackVelocity = o2::upgrade::computeParticleVelocity(particle.p(), pdgDB->GetParticle(particle.pdgCode())->Mass()); @@ -152,8 +154,8 @@ struct OnTheFlyDecayer { for (o2::upgrade::OTFParticle daughter : decayStack) { daughter.setIndicesMother(i, i); daughter.setCollisionId(mCollisionId); - daughter.setIsAlive(true); - daughter.setIsPrimary(false); + daughter.setBitOn(o2::upgrade::DecayerBits::IsAlive); + daughter.setBitOff(o2::upgrade::DecayerBits::IsPrimary); daughter.setProductionTime(trackTimeNS); allParticles.push_back(daughter); ndau++; @@ -202,8 +204,9 @@ struct OnTheFlyDecayer { } else { histos.fill(HIST("hNaNBookkeeping"), 0); } - + // todo: status codes + tableOTFDecayerBits(otfParticle.getBitsValue()); tableMcParticles(otfParticle.collisionId(), otfParticle.pdgCode(), otfParticle.statusCode(), otfParticle.flags(), otfParticle.getMotherSpan(), otfParticle.getDaughters().data(), otfParticle.weight(), otfParticle.px(), otfParticle.py(), otfParticle.pz(), otfParticle.e(), diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx index 78f6772fbe0..6140ff56b0b 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -1930,7 +1930,8 @@ struct OnTheFlyTracker { } } - void processConfigurationDev(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const int icfg) + template + void processConfigurationDev(aod::McCollision const& mcCollision, TMcParticles const& mcParticles, const int icfg) { const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; tracksAlice3.clear(); @@ -1997,11 +1998,11 @@ struct OnTheFlyTracker { bool reconstructed = false; int nTrkHits = 0; - if (enablePrimarySmearing && mcParticle.isPhysicalPrimary()) { + if (enablePrimarySmearing && otfParticle.checkBit(o2::upgrade::DecayerBits::IsPrimary)) { o2::upgrade::convertMCParticleToO2Track(mcParticle, trackParCov, pdgDB); reconstructed = mSmearer[icfg]->smearTrack(trackParCov, mcParticle.pdgCode(), dNdEta); nTrkHits = fastTrackerSettings.minSiliconHits; - } else if (enableSecondarySmearing) { + } else if (enableSecondarySmearing && !otfParticle.checkBit(o2::upgrade::DecayerBits::IsPrimary) && otfParticle.checkBit(o2::upgrade::DecayerBits::ProducedByDecayer) && otfParticle.checkBit(o2::upgrade::DecayerBits::IsAlive)) { o2::track::TrackParCov perfectTrackParCov; o2::upgrade::convertMCParticleToO2Track(mcParticle, perfectTrackParCov, pdgDB); perfectTrackParCov.setPID(pdgCodeToPID(mcParticle.pdgCode())); @@ -2071,7 +2072,7 @@ struct OnTheFlyTracker { fillTracksInfo(ghostTracksAlice3, primaryVertex, icfg); } - void processDecayer(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles) + void processDecayer(aod::McCollision const& mcCollision, soa::Join const& mcParticles) { for (size_t icfg = 0; icfg < mSmearer.size(); ++icfg) { processConfigurationDev(mcCollision, mcParticles, static_cast(icfg)); diff --git a/ALICE3/TableProducer/alice3strangenessFinder.cxx b/ALICE3/TableProducer/alice3strangenessFinder.cxx index c180a6ea907..f1366e95732 100644 --- a/ALICE3/TableProducer/alice3strangenessFinder.cxx +++ b/ALICE3/TableProducer/alice3strangenessFinder.cxx @@ -418,7 +418,7 @@ struct Alice3strangenessFinder { } template - void processFindV0CandidateNoPid(TCollision collision, TTracksGrouped negTracksGrouped, TTracksGrouped posTracksGrouped, TTracksGrouped bachTracksGrouped) + void processFindV0CandidateNoPid(const TCollision& collision, const TTracksGrouped& negTracksGrouped, const TTracksGrouped& posTracksGrouped, const TTracksGrouped& bachTracksGrouped) { const std::array vtx = {collision.posX(), collision.posY(), collision.posZ()}; histos.fill(HIST("hEventCounter"), 1.0); From 4c2cf28e08fa1b832cdba019574c64352a7b5f1c Mon Sep 17 00:00:00 2001 From: jesgum Date: Fri, 29 May 2026 11:49:50 +0200 Subject: [PATCH 09/12] Add Anton's changes --- ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx | 86 ++++++++++---------- 1 file changed, 41 insertions(+), 45 deletions(-) diff --git a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx index 1de90499abe..7748ed7b4bc 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx @@ -17,8 +17,8 @@ #include "ALICE3/Core/Decayer.h" #include "ALICE3/Core/OTFParticle.h" -#include "ALICE3/DataModel/tracksAlice3.h" #include "ALICE3/Core/TrackUtilities.h" +#include "ALICE3/DataModel/tracksAlice3.h" #include #include @@ -40,7 +40,6 @@ #include #include #include -#include #include #include @@ -67,8 +66,10 @@ static const std::vector pdgCodes{PDG_t::kK0Short, PDG_t::kOmegaMinus, PDG_t::kOmegaPlusBar}; -// Witchcraft -namespace o2::aod { O2ORIGIN("TMP"); } +namespace o2::aod +{ +O2ORIGIN("TMP"); +} struct OnTheFlyDecayer { Produces tableMcCollisions; @@ -121,7 +122,7 @@ struct OnTheFlyDecayer { void decayParticles(const int start, const int stop) { int ndau = 0; - for (int i = start; i < stop; i++) { + for (int i = start; i < stop; ++i) { o2::upgrade::OTFParticle& particle = allParticles[i]; if (particle.isFromMcParticles()) { particle.setBitOn(o2::upgrade::DecayerBits::IsPrimary); @@ -169,49 +170,44 @@ struct OnTheFlyDecayer { decayParticles(stop, stop + ndau); } - void process(aod::McCollisions_001From> const& mcCollisions, aod::McParticles_001From> const& mcParticles) + void process(aod::McCollisions_001From>::iterator const& collision, aod::McParticles_001From> const& mcParticles) { - for (const auto& collision : mcCollisions) { - allParticles.clear(); - - // Reproduce collision table to have AOD origin - mCollisionId = collision.globalIndex(); - tableMcCollisions(collision.bcId(), - collision.generatorsID(), - collision.posX(), - collision.posY(), - collision.posZ(), - collision.t(), - collision.weight(), - collision.impactParameter(), - collision.eventPlaneAngle()); - - // First we copy the particles from the table into a vector that is extendable - for (int index{0}; index < static_cast(mcParticles.size()); ++index) { - const auto& mcParticle = mcParticles.rawIteratorAt(index); - allParticles.push_back(o2::upgrade::OTFParticle{mcParticle}); - } + allParticles.clear(); + + // Reproduce collision table to have AOD origin + mCollisionId = collision.globalIndex(); + tableMcCollisions(collision.bcId(), + collision.generatorsID(), + collision.posX(), + collision.posY(), + collision.posZ(), + collision.t(), + collision.weight(), + collision.impactParameter(), + collision.eventPlaneAngle()); + + // First we copy the particles from the table into a vector that is extendable + for (const auto& particle : mcParticles) { + allParticles.emplace_back(o2::upgrade::OTFParticle{particle}); + } + + // Do all decays + decayParticles(0, allParticles.size()); - // Do all decays - decayParticles(0, allParticles.size()); - - // Fill output table - for (int index{0}; index < static_cast(allParticles.size()); ++index) { - const auto& otfParticle = allParticles[index]; - - if (otfParticle.hasNaN()) { - histos.fill(HIST("hNaNBookkeeping"), 1); - } else { - histos.fill(HIST("hNaNBookkeeping"), 0); - } - - // todo: status codes - tableOTFDecayerBits(otfParticle.getBitsValue()); - tableMcParticles(otfParticle.collisionId(), otfParticle.pdgCode(), otfParticle.statusCode(), otfParticle.flags(), - otfParticle.getMotherSpan(), otfParticle.getDaughters().data(), otfParticle.weight(), - otfParticle.px(), otfParticle.py(), otfParticle.pz(), otfParticle.e(), - otfParticle.vx(), otfParticle.vy(), otfParticle.vz(), otfParticle.vt()); + // Fill output table + for (const auto& otfParticle : allParticles) { + if (otfParticle.hasNaN()) { + histos.fill(HIST("hNaNBookkeeping"), 1); + } else { + histos.fill(HIST("hNaNBookkeeping"), 0); } + + // todo: status codes + tableOTFDecayerBits(otfParticle.getBitsValue()); + tableMcParticles(otfParticle.collisionId(), otfParticle.pdgCode(), otfParticle.statusCode(), otfParticle.flags(), + otfParticle.getMotherSpan(), otfParticle.getDaughters().data(), otfParticle.weight(), + otfParticle.px(), otfParticle.py(), otfParticle.pz(), otfParticle.e(), + otfParticle.vx(), otfParticle.vy(), otfParticle.vz(), otfParticle.vt()); } } }; From 8b01d53c315f98a31e0c5880d11cfc045ca60d26 Mon Sep 17 00:00:00 2001 From: jesgum Date: Fri, 29 May 2026 13:48:25 +0200 Subject: [PATCH 10/12] update comment --- ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx index 7748ed7b4bc..b568364b80c 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx @@ -202,7 +202,6 @@ struct OnTheFlyDecayer { histos.fill(HIST("hNaNBookkeeping"), 0); } - // todo: status codes tableOTFDecayerBits(otfParticle.getBitsValue()); tableMcParticles(otfParticle.collisionId(), otfParticle.pdgCode(), otfParticle.statusCode(), otfParticle.flags(), otfParticle.getMotherSpan(), otfParticle.getDaughters().data(), otfParticle.weight(), From 04b94ccb59378b029c5db28030f8af3da07038ba Mon Sep 17 00:00:00 2001 From: jesgum Date: Fri, 29 May 2026 13:56:47 +0200 Subject: [PATCH 11/12] formatting --- ALICE3/Core/OTFParticle.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ALICE3/Core/OTFParticle.h b/ALICE3/Core/OTFParticle.h index 73b5183ffed..9f93ea59597 100644 --- a/ALICE3/Core/OTFParticle.h +++ b/ALICE3/Core/OTFParticle.h @@ -58,7 +58,7 @@ class OTFParticle if (particle.has_mothers()) { mIndicesMother = {particle.mothersIds().front(), particle.mothersIds().back()}; } - if constexpr ( requires { particle.decayerBits(); } ) { + if constexpr (requires { particle.decayerBits(); }) { mBits = particle.decayerBits(); } else { // If we are here, we created particle in the standard workflow -- without secondaries @@ -162,7 +162,7 @@ class OTFParticle // Bits bool checkBit(DecayerBits bit) const { return mBits.test(static_cast(bit)); } void setBit(DecayerBits bit, bool value = true) { mBits.set(static_cast(bit), value); } - void setBitOn(DecayerBits bit) { mBits.set(static_cast(bit), true); } + void setBitOn(DecayerBits bit) { mBits.set(static_cast(bit), true); } void setBitOff(DecayerBits bit) { mBits.set(static_cast(bit), false); } std::bitset<8> getBits() const { return mBits; } From b93ae928536a694fae4006968ac8df187193d075 Mon Sep 17 00:00:00 2001 From: jesgum Date: Fri, 29 May 2026 14:07:55 +0200 Subject: [PATCH 12/12] megalinter fix --- ALICE3/TableProducer/alice3strangenessFinder.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/ALICE3/TableProducer/alice3strangenessFinder.cxx b/ALICE3/TableProducer/alice3strangenessFinder.cxx index f1366e95732..3599bc12d97 100644 --- a/ALICE3/TableProducer/alice3strangenessFinder.cxx +++ b/ALICE3/TableProducer/alice3strangenessFinder.cxx @@ -56,6 +56,7 @@ #include #include #include +#include #include using namespace o2;