From 73ea449a958b57dc7929c6d50886f09b34a2e470 Mon Sep 17 00:00:00 2001 From: Gijs van Weelden <55794847+GijsvWeelden@users.noreply.github.com> Date: Tue, 16 Sep 2025 21:36:19 +0200 Subject: [PATCH 1/2] [PWGJE] V0 Jet Framework update * Added option to either save all jets or only those containing V0 candidates * Added option to select all MCP V0s or only those that decay to charged particles --- PWGJE/Core/JetFindingUtilities.h | 4 +-- PWGJE/Core/JetV0Utilities.h | 8 +++-- PWGJE/JetFinders/jetFinderV0.cxx | 13 ++++--- PWGJE/TableProducer/derivedDataProducer.cxx | 40 ++++++++++++++++++++- 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/PWGJE/Core/JetFindingUtilities.h b/PWGJE/Core/JetFindingUtilities.h index 2bb9b8375b4..0dc05a00168 100644 --- a/PWGJE/Core/JetFindingUtilities.h +++ b/PWGJE/Core/JetFindingUtilities.h @@ -271,7 +271,7 @@ bool analyseV0s(std::vector& inputParticles, T const& v0s, f * @param doHFJetFinding set whether only jets containing a HF candidate are saved */ template -void findJets(JetFinder& jetFinder, std::vector& inputParticles, float jetPtMin, float jetPtMax, std::vector jetRadius, float jetAreaFractionMin, T const& collision, U& jetsTable, V& constituentsTable, std::shared_ptr thnSparseJet, bool fillThnSparse, bool doCandidateJetFinding = false) +void findJets(JetFinder& jetFinder, std::vector& inputParticles, float jetPtMin, float jetPtMax, std::vector jetRadius, float jetAreaFractionMin, T const& collision, U& jetsTable, V& constituentsTable, std::shared_ptr thnSparseJet, bool fillThnSparse, bool doCandidateJetFinding = false, bool saveJetsWithoutCandidates = false) { auto jetRValues = static_cast>(jetRadius); jetFinder.jetPtMin = jetPtMin; @@ -296,7 +296,7 @@ void findJets(JetFinder& jetFinder, std::vector& inputPartic break; } } - if (!isCandidateJet) { + if (!isCandidateJet && !saveJetsWithoutCandidates) { continue; } } diff --git a/PWGJE/Core/JetV0Utilities.h b/PWGJE/Core/JetV0Utilities.h index e7495242e01..9885ff7ca5a 100644 --- a/PWGJE/Core/JetV0Utilities.h +++ b/PWGJE/Core/JetV0Utilities.h @@ -138,9 +138,13 @@ auto slicedPerV0Candidate(T const& table, U const& candidate, V const& perV0Cand } template -bool isV0Particle(T const& particles, U const& particle) +bool isV0Particle(T const& particles, U const& particle, bool onlyChargedDecays) { - return RecoDecay::isMatchedMCGen(particles, particle, +kK0Short, std::array{+kPiPlus, -kPiPlus}, true) || RecoDecay::isMatchedMCGen(particles, particle, +kLambda0, std::array{+kProton, -kPiPlus}, true) || RecoDecay::isMatchedMCGen(particles, particle, -kLambda0, std::array{-kProton, +kPiPlus}, true); + if (onlyChargedDecays) { + return RecoDecay::isMatchedMCGen(particles, particle, +kK0Short, std::array{+kPiPlus, -kPiPlus}, true) || RecoDecay::isMatchedMCGen(particles, particle, +kLambda0, std::array{+kProton, -kPiPlus}, true) || RecoDecay::isMatchedMCGen(particles, particle, -kLambda0, std::array{-kProton, +kPiPlus}, true); + } else { + return RecoDecay::isMatchedMCGen(particles, particle, +kK0Short, std::array{+kPiPlus, -kPiPlus}, true) || RecoDecay::isMatchedMCGen(particles, particle, +kK0Short, std::array{+kPi0, +kPi0}, true) || RecoDecay::isMatchedMCGen(particles, particle, +kLambda0, std::array{+kProton, -kPiPlus}, true) || RecoDecay::isMatchedMCGen(particles, particle, +kLambda0, std::array{+kNeutron, +kPi0}, true) || RecoDecay::isMatchedMCGen(particles, particle, -kLambda0, std::array{-kProton, +kPiPlus}, true) || RecoDecay::isMatchedMCGen(particles, particle, -kLambda0, std::array{+kNeutron, +kPi0}, true); + } } enum JV0ParticleDecays { diff --git a/PWGJE/JetFinders/jetFinderV0.cxx b/PWGJE/JetFinders/jetFinderV0.cxx index ef4aaba93ab..2a7756199b5 100644 --- a/PWGJE/JetFinders/jetFinderV0.cxx +++ b/PWGJE/JetFinders/jetFinderV0.cxx @@ -93,6 +93,7 @@ struct JetFinderV0Task { Configurable fillTHnSparse{"fillTHnSparse", true, "switch to fill the THnSparse"}; Configurable jetExtraParam{"jetExtraParam", -99.0, "sets the _extra_param in fastjet"}; Configurable useV0SignalFlags{"useV0SignalFlags", true, "use V0 signal flags table"}; + Configurable saveJetsWithoutCandidates{"saveJetsWithoutCandidates", false, "save all jets, even those without V0s"}; Service pdgDatabase; int trackSelection = -1; @@ -171,7 +172,9 @@ struct JetFinderV0Task { } inputParticles.clear(); if (!jetfindingutilities::analyseV0s(inputParticles, candidates, candPtMin, candPtMax, candYMin, candYMax, candIndex, useV0SignalFlags)) { - return; + if (!saveJetsWithoutCandidates) { + return; + } } /* @@ -183,7 +186,7 @@ struct JetFinderV0Task { */ jetfindingutilities::analyseTracksMultipleCandidates(inputParticles, tracks, trackSelection, trackingEfficiency, candidates); - jetfindingutilities::findJets(jetFinder, inputParticles, minJetPt, maxJetPt, jetRadius, jetAreaFractionMin, collision, jetsTableInput, constituentsTableInput, registry.get(HIST("hJet")), fillTHnSparse, true); + jetfindingutilities::findJets(jetFinder, inputParticles, minJetPt, maxJetPt, jetRadius, jetAreaFractionMin, collision, jetsTableInput, constituentsTableInput, registry.get(HIST("hJet")), fillTHnSparse, true, saveJetsWithoutCandidates); } template @@ -192,10 +195,12 @@ struct JetFinderV0Task { inputParticles.clear(); if (!jetfindingutilities::analyseV0s(inputParticles, candidates, candPtMin, candPtMax, candYMin, candYMax, candIndex, useV0SignalFlags)) { - return; + if (!saveJetsWithoutCandidates) { + return; + } } jetfindingutilities::analyseParticles(inputParticles, particleSelection, jetTypeParticleLevel, particles, pdgDatabase, &candidates); - jetfindingutilities::findJets(jetFinder, inputParticles, minJetPt, maxJetPt, jetRadius, jetAreaFractionMin, collision, jetsTable, constituentsTable, registry.get(HIST("hJetMCP")), fillTHnSparse, true); + jetfindingutilities::findJets(jetFinder, inputParticles, minJetPt, maxJetPt, jetRadius, jetAreaFractionMin, collision, jetsTable, constituentsTable, registry.get(HIST("hJetMCP")), fillTHnSparse, true, saveJetsWithoutCandidates); } void processDummy(aod::JetCollisions const&) diff --git a/PWGJE/TableProducer/derivedDataProducer.cxx b/PWGJE/TableProducer/derivedDataProducer.cxx index c3de10e5e90..ae23535c546 100644 --- a/PWGJE/TableProducer/derivedDataProducer.cxx +++ b/PWGJE/TableProducer/derivedDataProducer.cxx @@ -763,8 +763,9 @@ struct JetDerivedDataProducerTask { void processV0MC(aod::McCollision const& mcCollision, aod::McParticles const& particles) { // can loop over McV0Labels tables if we want to only store matched V0Particles bool filledV0McCollisionTable = false; + bool onlyChargedDecays = false; for (auto const& particle : particles) { - if (jetv0utilities::isV0Particle(particles, particle)) { + if (jetv0utilities::isV0Particle(particles, particle, onlyChargedDecays)) { if (!filledV0McCollisionTable) { products.jV0McCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); products.jV0McCollisionIdsTable(mcCollision.globalIndex()); @@ -796,6 +797,43 @@ struct JetDerivedDataProducerTask { } PROCESS_SWITCH(JetDerivedDataProducerTask, processV0MC, "produces V0 particles", false); + void processV0MCChargedDecays(aod::McCollision const& mcCollision, aod::McParticles const& particles) + { // can loop over McV0Labels tables if we want to only store matched V0Particles + bool filledV0McCollisionTable = false; + bool onlyChargedDecays = true; + for (auto const& particle : particles) { + if (jetv0utilities::isV0Particle(particles, particle, onlyChargedDecays)) { + if (!filledV0McCollisionTable) { + products.jV0McCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); + products.jV0McCollisionIdsTable(mcCollision.globalIndex()); + filledV0McCollisionTable = true; + } + std::vector mothersId; + if (particle.has_mothers()) { + auto mothersIdTemps = particle.mothersIds(); + for (auto mothersIdTemp : mothersIdTemps) { + mothersId.push_back(mothersIdTemp); + } + } + int daughtersId[2] = {-1, -1}; + auto i = 0; + if (particle.has_daughters()) { + for (auto daughterId : particle.daughtersIds()) { + if (i > 1) { + break; + } + daughtersId[i] = daughterId; + i++; + } + } + auto pdgParticle = pdgDatabase->GetParticle(particle.pdgCode()); + products.jV0McsTable(products.jV0McCollisionsTable.lastIndex(), particle.pt(), particle.eta(), particle.phi(), particle.y(), particle.e(), pdgParticle->Mass(), particle.pdgCode(), particle.getGenStatusCode(), particle.getHepMCStatusCode(), particle.isPhysicalPrimary(), jetv0utilities::setV0ParticleDecayBit(particles, particle)); + products.jV0McIdsTable(mcCollision.globalIndex(), particle.globalIndex(), mothersId, daughtersId); + } + } + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processV0MCChargedDecays, "produces V0 particles that decay to charged particles", false); + void processDielectronCollisions(aod::ReducedEventsInfo::iterator const& DielectronCollision) { products.jDielectronCollisionIdsTable(DielectronCollision.collisionId()); From 83c8796d7a2eb31a503f5b0ba9d801dcc190e5fe Mon Sep 17 00:00:00 2001 From: Gijs van Weelden <55794847+GijsvWeelden@users.noreply.github.com> Date: Fri, 26 Sep 2025 12:26:17 +0200 Subject: [PATCH 2/2] Implemented comments Nima --- PWGJE/Core/JetFindingUtilities.h | 4 +- PWGJE/Core/JetV0Utilities.h | 4 +- PWGJE/JetFinders/jetFinderV0.cxx | 10 ++--- PWGJE/TableProducer/derivedDataProducer.cxx | 41 +-------------------- 4 files changed, 11 insertions(+), 48 deletions(-) diff --git a/PWGJE/Core/JetFindingUtilities.h b/PWGJE/Core/JetFindingUtilities.h index 0dc05a00168..2bb9b8375b4 100644 --- a/PWGJE/Core/JetFindingUtilities.h +++ b/PWGJE/Core/JetFindingUtilities.h @@ -271,7 +271,7 @@ bool analyseV0s(std::vector& inputParticles, T const& v0s, f * @param doHFJetFinding set whether only jets containing a HF candidate are saved */ template -void findJets(JetFinder& jetFinder, std::vector& inputParticles, float jetPtMin, float jetPtMax, std::vector jetRadius, float jetAreaFractionMin, T const& collision, U& jetsTable, V& constituentsTable, std::shared_ptr thnSparseJet, bool fillThnSparse, bool doCandidateJetFinding = false, bool saveJetsWithoutCandidates = false) +void findJets(JetFinder& jetFinder, std::vector& inputParticles, float jetPtMin, float jetPtMax, std::vector jetRadius, float jetAreaFractionMin, T const& collision, U& jetsTable, V& constituentsTable, std::shared_ptr thnSparseJet, bool fillThnSparse, bool doCandidateJetFinding = false) { auto jetRValues = static_cast>(jetRadius); jetFinder.jetPtMin = jetPtMin; @@ -296,7 +296,7 @@ void findJets(JetFinder& jetFinder, std::vector& inputPartic break; } } - if (!isCandidateJet && !saveJetsWithoutCandidates) { + if (!isCandidateJet) { continue; } } diff --git a/PWGJE/Core/JetV0Utilities.h b/PWGJE/Core/JetV0Utilities.h index 9885ff7ca5a..107b67c0ee8 100644 --- a/PWGJE/Core/JetV0Utilities.h +++ b/PWGJE/Core/JetV0Utilities.h @@ -138,9 +138,9 @@ auto slicedPerV0Candidate(T const& table, U const& candidate, V const& perV0Cand } template -bool isV0Particle(T const& particles, U const& particle, bool onlyChargedDecays) +bool isV0Particle(T const& particles, U const& particle, bool v0ChargedDecaysOnly) { - if (onlyChargedDecays) { + if (v0ChargedDecaysOnly) { return RecoDecay::isMatchedMCGen(particles, particle, +kK0Short, std::array{+kPiPlus, -kPiPlus}, true) || RecoDecay::isMatchedMCGen(particles, particle, +kLambda0, std::array{+kProton, -kPiPlus}, true) || RecoDecay::isMatchedMCGen(particles, particle, -kLambda0, std::array{-kProton, +kPiPlus}, true); } else { return RecoDecay::isMatchedMCGen(particles, particle, +kK0Short, std::array{+kPiPlus, -kPiPlus}, true) || RecoDecay::isMatchedMCGen(particles, particle, +kK0Short, std::array{+kPi0, +kPi0}, true) || RecoDecay::isMatchedMCGen(particles, particle, +kLambda0, std::array{+kProton, -kPiPlus}, true) || RecoDecay::isMatchedMCGen(particles, particle, +kLambda0, std::array{+kNeutron, +kPi0}, true) || RecoDecay::isMatchedMCGen(particles, particle, -kLambda0, std::array{-kProton, +kPiPlus}, true) || RecoDecay::isMatchedMCGen(particles, particle, -kLambda0, std::array{+kNeutron, +kPi0}, true); diff --git a/PWGJE/JetFinders/jetFinderV0.cxx b/PWGJE/JetFinders/jetFinderV0.cxx index 2a7756199b5..69e9f5680ee 100644 --- a/PWGJE/JetFinders/jetFinderV0.cxx +++ b/PWGJE/JetFinders/jetFinderV0.cxx @@ -93,7 +93,7 @@ struct JetFinderV0Task { Configurable fillTHnSparse{"fillTHnSparse", true, "switch to fill the THnSparse"}; Configurable jetExtraParam{"jetExtraParam", -99.0, "sets the _extra_param in fastjet"}; Configurable useV0SignalFlags{"useV0SignalFlags", true, "use V0 signal flags table"}; - Configurable saveJetsWithoutCandidates{"saveJetsWithoutCandidates", false, "save all jets, even those without V0s"}; + Configurable saveJetsWithCandidatesOnly{"saveJetsWithCandidatesOnly", true, "only save jets if they contain a V0"}; Service pdgDatabase; int trackSelection = -1; @@ -172,7 +172,7 @@ struct JetFinderV0Task { } inputParticles.clear(); if (!jetfindingutilities::analyseV0s(inputParticles, candidates, candPtMin, candPtMax, candYMin, candYMax, candIndex, useV0SignalFlags)) { - if (!saveJetsWithoutCandidates) { + if (saveJetsWithCandidatesOnly) { return; } } @@ -186,7 +186,7 @@ struct JetFinderV0Task { */ jetfindingutilities::analyseTracksMultipleCandidates(inputParticles, tracks, trackSelection, trackingEfficiency, candidates); - jetfindingutilities::findJets(jetFinder, inputParticles, minJetPt, maxJetPt, jetRadius, jetAreaFractionMin, collision, jetsTableInput, constituentsTableInput, registry.get(HIST("hJet")), fillTHnSparse, true, saveJetsWithoutCandidates); + jetfindingutilities::findJets(jetFinder, inputParticles, minJetPt, maxJetPt, jetRadius, jetAreaFractionMin, collision, jetsTableInput, constituentsTableInput, registry.get(HIST("hJet")), fillTHnSparse, saveJetsWithCandidatesOnly); } template @@ -195,12 +195,12 @@ struct JetFinderV0Task { inputParticles.clear(); if (!jetfindingutilities::analyseV0s(inputParticles, candidates, candPtMin, candPtMax, candYMin, candYMax, candIndex, useV0SignalFlags)) { - if (!saveJetsWithoutCandidates) { + if (saveJetsWithCandidatesOnly) { return; } } jetfindingutilities::analyseParticles(inputParticles, particleSelection, jetTypeParticleLevel, particles, pdgDatabase, &candidates); - jetfindingutilities::findJets(jetFinder, inputParticles, minJetPt, maxJetPt, jetRadius, jetAreaFractionMin, collision, jetsTable, constituentsTable, registry.get(HIST("hJetMCP")), fillTHnSparse, true, saveJetsWithoutCandidates); + jetfindingutilities::findJets(jetFinder, inputParticles, minJetPt, maxJetPt, jetRadius, jetAreaFractionMin, collision, jetsTable, constituentsTable, registry.get(HIST("hJetMCP")), fillTHnSparse, saveJetsWithCandidatesOnly); } void processDummy(aod::JetCollisions const&) diff --git a/PWGJE/TableProducer/derivedDataProducer.cxx b/PWGJE/TableProducer/derivedDataProducer.cxx index ae23535c546..1f736f6b064 100644 --- a/PWGJE/TableProducer/derivedDataProducer.cxx +++ b/PWGJE/TableProducer/derivedDataProducer.cxx @@ -147,6 +147,7 @@ struct JetDerivedDataProducerTask { Configurable ccdbURL{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable includeTriggers{"includeTriggers", false, "fill the collision information with software trigger decisions"}; Configurable includeHadronicRate{"includeHadronicRate", true, "fill the collision information with the hadronic rate"}; + Configurable v0ChargedDecaysOnly{"v0ChargedDecaysOnly", true, "store V0s (at particle-level) only if they decay to charged particles"}; Preslice perClusterCells = aod::emcalclustercell::emcalclusterId; Preslice perClusterTracks = aod::emcalclustercell::emcalclusterId; @@ -763,9 +764,8 @@ struct JetDerivedDataProducerTask { void processV0MC(aod::McCollision const& mcCollision, aod::McParticles const& particles) { // can loop over McV0Labels tables if we want to only store matched V0Particles bool filledV0McCollisionTable = false; - bool onlyChargedDecays = false; for (auto const& particle : particles) { - if (jetv0utilities::isV0Particle(particles, particle, onlyChargedDecays)) { + if (jetv0utilities::isV0Particle(particles, particle, v0ChargedDecaysOnly)) { if (!filledV0McCollisionTable) { products.jV0McCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); products.jV0McCollisionIdsTable(mcCollision.globalIndex()); @@ -797,43 +797,6 @@ struct JetDerivedDataProducerTask { } PROCESS_SWITCH(JetDerivedDataProducerTask, processV0MC, "produces V0 particles", false); - void processV0MCChargedDecays(aod::McCollision const& mcCollision, aod::McParticles const& particles) - { // can loop over McV0Labels tables if we want to only store matched V0Particles - bool filledV0McCollisionTable = false; - bool onlyChargedDecays = true; - for (auto const& particle : particles) { - if (jetv0utilities::isV0Particle(particles, particle, onlyChargedDecays)) { - if (!filledV0McCollisionTable) { - products.jV0McCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); - products.jV0McCollisionIdsTable(mcCollision.globalIndex()); - filledV0McCollisionTable = true; - } - std::vector mothersId; - if (particle.has_mothers()) { - auto mothersIdTemps = particle.mothersIds(); - for (auto mothersIdTemp : mothersIdTemps) { - mothersId.push_back(mothersIdTemp); - } - } - int daughtersId[2] = {-1, -1}; - auto i = 0; - if (particle.has_daughters()) { - for (auto daughterId : particle.daughtersIds()) { - if (i > 1) { - break; - } - daughtersId[i] = daughterId; - i++; - } - } - auto pdgParticle = pdgDatabase->GetParticle(particle.pdgCode()); - products.jV0McsTable(products.jV0McCollisionsTable.lastIndex(), particle.pt(), particle.eta(), particle.phi(), particle.y(), particle.e(), pdgParticle->Mass(), particle.pdgCode(), particle.getGenStatusCode(), particle.getHepMCStatusCode(), particle.isPhysicalPrimary(), jetv0utilities::setV0ParticleDecayBit(particles, particle)); - products.jV0McIdsTable(mcCollision.globalIndex(), particle.globalIndex(), mothersId, daughtersId); - } - } - } - PROCESS_SWITCH(JetDerivedDataProducerTask, processV0MCChargedDecays, "produces V0 particles that decay to charged particles", false); - void processDielectronCollisions(aod::ReducedEventsInfo::iterator const& DielectronCollision) { products.jDielectronCollisionIdsTable(DielectronCollision.collisionId());