From bc4cf4aab054caba459b7fa5c6081d369160be16 Mon Sep 17 00:00:00 2001 From: Francesca Ercolessi Date: Wed, 16 Sep 2026 14:17:30 +0200 Subject: [PATCH 1/2] fix bugs and improve Gen process performance --- .../Tasks/Nuspex/hadronnucleicorrelation.cxx | 332 +++++++----------- 1 file changed, 129 insertions(+), 203 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx index d516e1e7a64..e719044364c 100644 --- a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx +++ b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -117,6 +118,7 @@ struct HadronNucleiCorrelation { Configurable nsigmaElPr{"nsigmaElPr", 1.0f, "cut nsigma TPC El for protons"}; Configurable nsigmaElDe{"nsigmaElDe", 3.0f, "cut nsigma TPC El for protons"}; Configurable nsigmaTOF{"nsigmaTOF", 3.5f, "cut nsigma TOF"}; + Configurable nsigmaQuadratic{"nsigmaQuadratic", 3.0f, "cut on sqrt(nsigmaTPC^2 + nsigmaTOF^2), used above the TOF pT threshold when doQuadraticPID is on"}; Configurable nsigmaITSPr{"nsigmaITSPr", -2.0f, "cut nsigma ITS Pr"}; Configurable nsigmaITSDe{"nsigmaITSDe", -2.0f, "cut nsigma ITS De"}; Configurable doITSPID{"doITSPID", true, "do ITS PID"}; @@ -173,6 +175,27 @@ struct HadronNucleiCorrelation { TH2F* hEffPtEtaAntiProton = nullptr; TH2F* hEffPtEtaDeuteron = nullptr; TH2F* hEffPtEtaAntiDeuteron = nullptr; + bool correctionsLoaded = false; // true only if all four efficiency histograms above were retrieved successfully + + // Generated-level pairing: PDG codes of the two species selected by `mode` (set in init) + int pdgPart0 = 0; + int pdgPart1 = 0; + + // Lightweight copy of a generated particle, so that the generated-level pairing runs on + // compact candidate vectors instead of re-reading the full MC particle table for every pair + struct GenCandidate { + float ptVal, etaVal, phiVal; + float pt() const { return ptVal; } + float eta() const { return etaVal; } + float phi() const { return phiVal; } + }; + + // Per-collision information needed for generated-level same- and mixed-event pairing + struct GenCollisionCache { + float mult = 0.f; // charged primaries with |eta| < 1, used for the mixing bins + std::vector cand0; // particles matching pdgPart0 + std::vector cand1; // particles matching pdgPart1 + }; Service ccdb{}; o2::ccdb::CcdbApi ccdbApi; @@ -189,6 +212,9 @@ struct HadronNucleiCorrelation { if (doCorrection) { getCorrection(ccdb, TString(fCorrectionPath), TString(fCorrectionHisto)); + if (!correctionsLoaded) { + LOG(fatal) << "doCorrection is enabled but the efficiency histograms could not be retrieved from " << fCorrectionPath.value; + } } const AxisSpec ptBinnedAxis = {pTBins, "#it{p}_{T} of #bar{p} (GeV/#it{c})"}; @@ -215,27 +241,43 @@ struct HadronNucleiCorrelation { switch (mode) { case kDbarPbar: // 0 name = "AntiDeAntiPr"; + pdgPart0 = -o2::constants::physics::Pdg::kDeuteron; + pdgPart1 = -PDG_t::kProton; break; case kDP: // 1 name = "DePr"; + pdgPart0 = o2::constants::physics::Pdg::kDeuteron; + pdgPart1 = PDG_t::kProton; break; case kDbarP: // 2 name = "AntiDePr"; + pdgPart0 = -o2::constants::physics::Pdg::kDeuteron; + pdgPart1 = PDG_t::kProton; break; case kDPbar: // 3 name = "DeAntiPr"; + pdgPart0 = o2::constants::physics::Pdg::kDeuteron; + pdgPart1 = -PDG_t::kProton; break; case kPbarP: // 4 name = "AntiPrPr"; + pdgPart0 = -PDG_t::kProton; + pdgPart1 = PDG_t::kProton; break; case kPbarPbar: // 5 name = "AntiPrAntiPr"; + pdgPart0 = -PDG_t::kProton; + pdgPart1 = -PDG_t::kProton; break; case kPP: // 6 name = "PrPr"; + pdgPart0 = PDG_t::kProton; + pdgPart1 = PDG_t::kProton; break; case kPPbar: // 7 name = "PrAntiPr"; + pdgPart0 = PDG_t::kProton; + pdgPart1 = -PDG_t::kProton; break; default: LOG(fatal) << "Unhandled case " << mode; @@ -442,7 +484,7 @@ struct HadronNucleiCorrelation { o2::aod::singletrackselector::unPack(o2::aod::singletrackselector::storedTpcCrossedRowsOverFindableCls) >= minTPCnCrossedRowsOverFindableCls && o2::aod::singletrackselector::unPack(o2::aod::singletrackselector::storedItsChi2NCl) <= maxchi2ITS && nabs(o2::aod::singletrackselector::unPack(o2::aod::singletrackselector::storedDcaXY)) <= maxDCAxy && - nabs(o2::aod::singletrackselector::unPack(o2::aod::singletrackselector::storedDcaXY)) <= maxDCAz && + nabs(o2::aod::singletrackselector::unPack(o2::aod::singletrackselector::storedDcaZ)) <= maxDCAz && nabs(o2::aod::singletrackselector::eta) <= etaCut; Filter simvertexFilter = nabs(o2::aod::mccollision::posZ) <= cutzVertex; @@ -455,7 +497,7 @@ struct HadronNucleiCorrelation { const bool isTPCElRejection = rejectionEl && track.beta() < BetahasTOFthr && track.pt() < pTthrprTPCEl && track.tpcNSigmaEl() >= nsigmaElPr; const bool isITSPID = track.itsNSigmaPr() > nsigmaITSPr; - const bool isQuadraticPID = std::hypot(track.tpcNSigmaPr(), track.tofNSigmaPr()) < nsigmaTPC; + const bool isQuadraticPID = std::hypot(track.tpcNSigmaPr(), track.tofNSigmaPr()) < nsigmaQuadratic; // Check if the sign of the track matches the expected sign for protons or antiprotons const bool signCheck = (sign > 0 && track.sign() > 0) || (sign < 0 && track.sign() < 0); @@ -491,7 +533,7 @@ struct HadronNucleiCorrelation { const bool isTPCElRejection = rejectionEl && track.beta() < BetahasTOFthr && track.pt() < pTthrdeTPCEl && track.tpcNSigmaEl() >= nsigmaElDe; const bool isITSPID = track.itsNSigmaDe() > nsigmaITSDe; - const bool isQuadraticPID = std::hypot(track.tpcNSigmaDe(), track.tofNSigmaDe()) < nsigmaTPC; + const bool isQuadraticPID = std::hypot(track.tpcNSigmaDe(), track.tofNSigmaDe()) < nsigmaQuadratic; // Check if the sign of the track matches the expected sign for deuterons or antideuterons const bool signCheck = (sign > 0 && track.sign() > 0) || (sign < 0 && track.sign() < 0); @@ -506,7 +548,7 @@ struct HadronNucleiCorrelation { } } } else { - if (track.pt() < pTthrprTOF) { + if (track.pt() < pTthrdeTOF) { if (isTPCPID) { if (!doITSPID || isITSPID) { return signCheck; @@ -557,7 +599,7 @@ struct HadronNucleiCorrelation { float corr0 = 1, corr1 = 1; - if (doCorrection) { // Apply corrections + if (doCorrection && correctionsLoaded) { // Apply corrections (only if all efficiency histograms were retrieved) switch (mode) { case kDbarPbar: corr0 = hEffPtEtaAntiDeuteron->Interpolate(part0.pt(), part0.eta()); @@ -668,30 +710,57 @@ struct HadronNucleiCorrelation { LOGP(info, "Opened histogram {}", Form("%s_antiproton", histname.Data())); LOGP(info, "Opened histogram {}", Form("%s_deuteron", histname.Data())); LOGP(info, "Opened histogram {}", Form("%s_antideuteron", histname.Data())); + correctionsLoaded = true; } + // Generated-level candidate selection, shared by same- and mixed-event processing: + // same cuts as the pairing (primary if requested, |eta| <= etaCut, PDG code of one of the two species) + template + void addGenCandidate(TParticle const& particle, GenCollisionCache& cache) + { + if (isPrim && !particle.isPhysicalPrimary()) { + return; + } + if (std::abs(particle.eta()) > etaCut) { + return; + } + const int pdg = particle.pdgCode(); + if (pdg != pdgPart0 && pdg != pdgPart1) { + return; + } + const GenCandidate cand{particle.pt(), particle.eta(), particle.phi()}; + if (pdg == pdgPart0) { + cache.cand0.push_back(cand); + } + if (pdg == pdgPart1) { + cache.cand1.push_back(cand); + } + } + + // Single pass over the particles of one generated collision: charged-primary multiplicity + // (|eta| < 1) for the mixing bins and the pairing candidates template - float getMCMultiplicity(TParticles const& particles) + GenCollisionCache buildGenCollisionCache(TParticles const& particles) { - float nCharged = 0.; + GenCollisionCache cache; for (const auto& mcParticle : particles) { + addGenCandidate(mcParticle, cache); if (!mcParticle.isPhysicalPrimary()) { continue; } - if (std::abs(mcParticle.eta()) > 1.0f) { continue; } - TParticlePDG* p = pdgDB->GetParticle(mcParticle.pdgCode()); + if (!p) { // unknown PDG code (e.g. exotic fragments not in the database) + continue; + } if (std::abs(p->Charge()) > 1E-3) { - nCharged++; + cache.mult++; } } - - registry.fill(HIST("hMult"), nCharged); - return nCharged; + return cache; } void processSameEvent(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks) @@ -840,6 +909,10 @@ struct HadronNucleiCorrelation { for (const auto& [part0, part1] : combinations(CombinationsFullIndexPolicy(tracks, tracks))) { + if (part0.globalIndex() == part1.globalIndex()) { + continue; + } + if (part0.tpcFractionSharedCls() > maxtpcSharedCls) { continue; } @@ -1078,6 +1151,10 @@ struct HadronNucleiCorrelation { for (const auto& [part0, part1] : combinations(CombinationsFullIndexPolicy(tracks, tracks))) { + if (part0.globalIndex() == part1.globalIndex()) { + continue; + } + if (removeSameBunchPileup && !part0.template singleCollSel_as().isNoSameBunchPileup()) { continue; } @@ -1836,6 +1913,9 @@ struct HadronNucleiCorrelation { registry.fill(HIST("Generated/hNEventsMC"), 0.5); + // Pairing candidates are collected during the QA loop below (which already visits every particle) + GenCollisionCache genCache; + for (const auto& particle : mcParticles) { auto fillGeneratedQa = [this, &particle](const float binPosition) { switch (particle.pdgCode()) { @@ -1894,6 +1974,14 @@ struct HadronNucleiCorrelation { } fillGeneratedQa(2.5); + // (anti)neutrons are accepted by fillGeneratedQa for QA counting only: they have no + // eta-phi-pt histogram and must not reach the switch below (whose default is fatal) + if (std::abs(particle.pdgCode()) == PDG_t::kNeutron) { + continue; + } + + addGenCandidate(particle, genCache); + switch (particle.pdgCode()) { case PDG_t::kProton: registry.fill(HIST("hGen_EtaPhiPt_Proton"), particle.eta(), particle.phi(), particle.pt()); @@ -1913,112 +2001,20 @@ struct HadronNucleiCorrelation { } } - if (mode == kPbarPbar || mode == kPP) { // Identical particle combinations - - for (const auto& [part0, part1] : combinations(CombinationsStrictlyUpperIndexPolicy(mcParticles, mcParticles))) { - - if (isPrim && !part0.isPhysicalPrimary()) { - continue; - } - if (isPrim && !part1.isPhysicalPrimary()) { - continue; - } - if (std::abs(part0.eta()) > etaCut) { - continue; + // Pairing on the compact candidate vectors only (table order is preserved, so the + // part0/part1 assignment is the same as with the full-table combinations) + if (pdgPart0 == pdgPart1) { // Identical particle combinations: each unordered pair once + const auto& cands = genCache.cand0; + for (size_t i = 0; i < cands.size(); i++) { + for (size_t j = i + 1; j < cands.size(); j++) { + fillHistogramsGen(cands[i], cands[j], false); } - if (std::abs(part1.eta()) > etaCut) { - continue; - } - - // mode 6 - if (mode == kPP) { - if (part0.pdgCode() != PDG_t::kProton) { - continue; - } - if (part1.pdgCode() != PDG_t::kProton) { - continue; - } - } - // mode 5 - if (mode == kPbarPbar) { - if (part0.pdgCode() != -PDG_t::kProton) { - continue; - } - if (part1.pdgCode() != -PDG_t::kProton) { - continue; - } - } - - fillHistogramsGen(part0, part1, false); } - } else { - - for (const auto& [part0, part1] : combinations(CombinationsFullIndexPolicy(mcParticles, mcParticles))) { - - if (isPrim && !part0.isPhysicalPrimary()) { - continue; - } - if (isPrim && !part1.isPhysicalPrimary()) { - continue; - } - if (std::abs(part0.eta()) > etaCut) { - continue; - } - if (std::abs(part1.eta()) > etaCut) { - continue; - } - - if (mode == kDbarPbar) { - if (part0.pdgCode() != -o2::constants::physics::Pdg::kDeuteron) { - continue; - } - if (part1.pdgCode() != -PDG_t::kProton) { - continue; - } - } - if (mode == kDP) { - if (part0.pdgCode() != o2::constants::physics::Pdg::kDeuteron) { - continue; - } - if (part1.pdgCode() != PDG_t::kProton) { - continue; - } - } - if (mode == kDbarP) { - if (part0.pdgCode() != -o2::constants::physics::Pdg::kDeuteron) { - continue; - } - if (part1.pdgCode() != PDG_t::kProton) { - continue; - } + for (const auto& part0 : genCache.cand0) { + for (const auto& part1 : genCache.cand1) { + fillHistogramsGen(part0, part1, false); } - if (mode == kDPbar) { - if (part0.pdgCode() != o2::constants::physics::Pdg::kDeuteron) { - continue; - } - if (part1.pdgCode() != -PDG_t::kProton) { - continue; - } - } - if (mode == kPbarP) { - if (part0.pdgCode() != -PDG_t::kProton) { - continue; - } - if (part1.pdgCode() != PDG_t::kProton) { - continue; - } - } - if (mode == kPPbar) { - if (part0.pdgCode() != PDG_t::kProton) { - continue; - } - if (part1.pdgCode() != -PDG_t::kProton) { - continue; - } - } - - fillHistogramsGen(part0, part1, false); } } } @@ -2029,103 +2025,33 @@ struct HadronNucleiCorrelation { void processMixedEventGen(SimCollisions const& mcCollisions, SimParticles const& mcParticles) { - auto getMultiplicity = [this, &mcParticles](SimCollisions::iterator const& collision) { + // One pass per collision: multiplicity for the mixing bins + pairing candidates. + // The mixing loop below never touches the MC particle table again. + std::unordered_map genCaches; + genCaches.reserve(mcCollisions.size()); + for (const auto& collision : mcCollisions) { auto particlesPerCol = mcParticles.sliceBy(perMcCollision, collision.globalIndex()); - auto multiplicity = getMCMultiplicity(particlesPerCol); - return multiplicity; + auto cache = buildGenCollisionCache(particlesPerCol); + registry.fill(HIST("hMult"), cache.mult); + genCaches.emplace(collision.globalIndex(), std::move(cache)); + } + + auto getMultiplicity = [&genCaches](SimCollisions::iterator const& collision) { + return genCaches.at(collision.globalIndex()).mult; }; using BinningTypeMC = FlexibleBinningPolicy, aod::mccollision::PosZ, decltype(getMultiplicity)>; BinningTypeMC colBinningGen{{getMultiplicity}, {confVtxBins, confMultBins}, true}; for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningGen, 5, -1, mcCollisions, mcCollisions)) { + const auto& cache1 = genCaches.at(collision1.globalIndex()); + const auto& cache2 = genCaches.at(collision2.globalIndex()); - auto groupPartsOne = mcParticles.sliceBy(perMcCollision, collision1.globalIndex()); - auto groupPartsTwo = mcParticles.sliceBy(perMcCollision, collision2.globalIndex()); - - // LOGF(info, "Mixed event collisions: (%d, %d) zvtx (%.1f, %.1f) mult (%.1f, %.1f)", collision1.globalIndex(), collision2.globalIndex(), collision1.posZ(), collision2.posZ(), getMCMultiplicity(groupPartsOne), getMCMultiplicity(groupPartsTwo)); - - for (const auto& [part0, part1] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { - - if (isPrim && !part0.isPhysicalPrimary()) { - continue; + // For identical species cand1 holds the same particles as cand0, so this covers both cases + for (const auto& part0 : cache1.cand0) { + for (const auto& part1 : cache2.cand1) { + fillHistogramsGen(part0, part1, true); } - if (isPrim && !part1.isPhysicalPrimary()) { - continue; - } - if (std::abs(part0.eta()) > etaCut) { - continue; - } - if (std::abs(part1.eta()) > etaCut) { - continue; - } - - if (mode == kDbarPbar) { - if (part0.pdgCode() != -o2::constants::physics::Pdg::kDeuteron) { - continue; - } - if (part1.pdgCode() != -PDG_t::kProton) { - continue; - } - } - if (mode == kDP) { - if (part0.pdgCode() != o2::constants::physics::Pdg::kDeuteron) { - continue; - } - if (part1.pdgCode() != PDG_t::kProton) { - continue; - } - } - if (mode == kDbarP) { - if (part0.pdgCode() != -o2::constants::physics::Pdg::kDeuteron) { - continue; - } - if (part1.pdgCode() != PDG_t::kProton) { - continue; - } - } - if (mode == kDPbar) { - if (part0.pdgCode() != o2::constants::physics::Pdg::kDeuteron) { - continue; - } - if (part1.pdgCode() != -PDG_t::kProton) { - continue; - } - } - if (mode == kPbarP) { - if (part0.pdgCode() != -PDG_t::kProton) { - continue; - } - if (part1.pdgCode() != PDG_t::kProton) { - continue; - } - } - if (mode == kPbarPbar) { - if (part0.pdgCode() != -PDG_t::kProton) { - continue; - } - if (part1.pdgCode() != -PDG_t::kProton) { - continue; - } - } - if (mode == kPP) { - if (part0.pdgCode() != PDG_t::kProton) { - continue; - } - if (part1.pdgCode() != PDG_t::kProton) { - continue; - } - } - if (mode == kPPbar) { - if (part0.pdgCode() != PDG_t::kProton) { - continue; - } - if (part1.pdgCode() != -PDG_t::kProton) { - continue; - } - } - - fillHistogramsGen(part0, part1, true); } } } From dfcb806edcc4f41f7304bcc979bf4f6331294977 Mon Sep 17 00:00:00 2001 From: Francesca Ercolessi Date: Wed, 16 Sep 2026 14:39:37 +0200 Subject: [PATCH 2/2] Fix Megalinter and add QA histos --- .../Tasks/Nuspex/hadronnucleicorrelation.cxx | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx index e719044364c..7e93956f83d 100644 --- a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx +++ b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx @@ -325,8 +325,10 @@ struct HadronNucleiCorrelation { const AxisSpec tofNSigmaAxis = {axisNSigma, "n#sigma TOF"}; const AxisSpec tpcNSigmaAxis = {axisNSigma, "n#sigma TPC"}; const AxisSpec itsNSigmaAxis = {axisNSigma, "n#sigma ITS"}; - registryQa.add("QA/h2dTPCTOF_Pr", "n#sigma TPC vs n#sigma TOF", {HistType::kTH2D, {tpcNSigmaAxis, tofNSigmaAxis}}); - registryQa.add("QA/h2dTPCTOF_AntiPr", "n#sigma TPC vs n#sigma TOF", {HistType::kTH2D, {tpcNSigmaAxis, tofNSigmaAxis}}); + registryQa.add("QA/h3dTPCTOF_Pr", "n#sigma TPC vs n#sigma TOF; n#sigma TPC;n#sigma TOF;p_{T} (GeV/c)", {HistType::kTH3D, {tpcNSigmaAxis, tofNSigmaAxis, ptAxis}}); + registryQa.add("QA/h3dTPCTOF_AntiPr", "n#sigma TPC vs n#sigma TOF; n#sigma TPC;n#sigma TOF;p_{T} (GeV/c)", {HistType::kTH3D, {tpcNSigmaAxis, tofNSigmaAxis, ptAxis}}); + registryQa.add("QA/h3dTPCTOF_De", "n#sigma TPC vs n#sigma TOF; n#sigma TPC;n#sigma TOF;p_{T} (GeV/c)", {HistType::kTH3D, {tpcNSigmaAxis, tofNSigmaAxis, ptAxis}}); + registryQa.add("QA/h3dTPCTOF_AntiDe", "n#sigma TPC vs n#sigma TOF; n#sigma TPC;n#sigma TOF;p_{T} (GeV/c)", {HistType::kTH3D, {tpcNSigmaAxis, tofNSigmaAxis, ptAxis}}); registryQa.add("QA/hnSigmaTPCVsPt_El", "n#sigma TPC vs p_{T} for e hypothesis (all tracks)", {HistType::kTH2D, {ptAxis, tpcNSigmaAxis}}); registryQa.add("QA/hnSigmaTPCVsPt_Pr", "n#sigma TPC vs p_{T} for p hypothesis (all tracks)", {HistType::kTH2D, {ptAxis, tpcNSigmaAxis}}); registryQa.add("QA/hnSigmaTPCVsPt_De", "n#sigma TPC vs p_{T} for d hypothesis (all tracks)", {HistType::kTH2D, {ptAxis, tpcNSigmaAxis}}); @@ -352,8 +354,6 @@ struct HadronNucleiCorrelation { registryQa.add("QA/hnSigmaTOFVsPt_De_AfterSel", "n#sigma TOF vs p_{T} for d hypothesis (all tracks)", {HistType::kTH2D, {ptAxis, tofNSigmaAxis}}); registryQa.add("QA/hnSigmaITSVsPt_Pr_AfterSel", "n#sigma ITS vs p_{T} for p hypothesis (all tracks)", {HistType::kTH2D, {ptAxis, itsNSigmaAxis}}); registryQa.add("QA/hnSigmaITSVsPt_De_AfterSel", "n#sigma ITS vs p_{T} for d hypothesis (all tracks)", {HistType::kTH2D, {ptAxis, itsNSigmaAxis}}); - registryQa.add("QA/h2dTPCTOF_Pr_AfterSel", "n#sigma TPC vs n#sigma TOF", {HistType::kTH2D, {tpcNSigmaAxis, tofNSigmaAxis}}); - registryQa.add("QA/h2dTPCTOF_AntiPr_AfterSel", "n#sigma TPC vs n#sigma TOF", {HistType::kTH2D, {tpcNSigmaAxis, tofNSigmaAxis}}); } } @@ -716,7 +716,7 @@ struct HadronNucleiCorrelation { // Generated-level candidate selection, shared by same- and mixed-event processing: // same cuts as the pairing (primary if requested, |eta| <= etaCut, PDG code of one of the two species) template - void addGenCandidate(TParticle const& particle, GenCollisionCache& cache) + void addGenCandidate(TParticle const& particle, GenCollisionCache& colCache) { if (isPrim && !particle.isPhysicalPrimary()) { return; @@ -730,10 +730,10 @@ struct HadronNucleiCorrelation { } const GenCandidate cand{particle.pt(), particle.eta(), particle.phi()}; if (pdg == pdgPart0) { - cache.cand0.push_back(cand); + colCache.cand0.push_back(cand); } if (pdg == pdgPart1) { - cache.cand1.push_back(cand); + colCache.cand1.push_back(cand); } } @@ -742,9 +742,9 @@ struct HadronNucleiCorrelation { template GenCollisionCache buildGenCollisionCache(TParticles const& particles) { - GenCollisionCache cache; + GenCollisionCache colCache; for (const auto& mcParticle : particles) { - addGenCandidate(mcParticle, cache); + addGenCandidate(mcParticle, colCache); if (!mcParticle.isPhysicalPrimary()) { continue; @@ -757,10 +757,10 @@ struct HadronNucleiCorrelation { continue; } if (std::abs(p->Charge()) > 1E-3) { - cache.mult++; + colCache.mult++; } } - return cache; + return colCache; } void processSameEvent(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks) @@ -812,8 +812,14 @@ struct HadronNucleiCorrelation { registryQa.fill(HIST("QA/hnSigmaTOFVsPt_De"), track.pt() * track.sign(), track.tofNSigmaDe()); registryQa.fill(HIST("QA/hnSigmaITSVsPt_Pr"), track.pt() * track.sign(), track.itsNSigmaPr()); registryQa.fill(HIST("QA/hnSigmaITSVsPt_De"), track.pt() * track.sign(), track.itsNSigmaDe()); - registryQa.fill(HIST("QA/h2dTPCTOF_AntiPr"), track.tpcNSigmaPr(), track.tofNSigmaPr()); - registryQa.fill(HIST("QA/h2dTPCTOF_Pr"), track.tpcNSigmaPr(), track.tofNSigmaPr()); + if (track.sign() > 0) { + registryQa.fill(HIST("QA/h3dTPCTOF_Pr"), track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); + registryQa.fill(HIST("QA/h3dTPCTOF_De"), track.tpcNSigmaDe(), track.tofNSigmaDe(), track.pt()); + } + if (track.sign() < 0) { + registryQa.fill(HIST("QA/h3dTPCTOF_AntiPr"), track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); + registryQa.fill(HIST("QA/h3dTPCTOF_AntiDe"), track.tpcNSigmaDe(), track.tofNSigmaDe(), track.pt()); + } if (isProton(track, -1)) { registryQa.fill(HIST("QA/hEtaAntiPr"), track.eta()); @@ -821,7 +827,6 @@ struct HadronNucleiCorrelation { registryQa.fill(HIST("QA/hnSigmaTOFVsPt_Pr_AfterSel"), track.pt() * track.sign(), track.tofNSigmaPr()); registryQa.fill(HIST("QA/hnSigmaTPCVsPt_Pr_AfterSel"), track.pt() * track.sign(), track.tpcNSigmaPr()); registryQa.fill(HIST("QA/hnSigmaITSVsPt_Pr_AfterSel"), track.pt() * track.sign(), track.itsNSigmaPr()); - registryQa.fill(HIST("QA/h2dTPCTOF_AntiPr_AfterSel"), track.tpcNSigmaPr(), track.tofNSigmaPr()); } if (isProton(track, +1)) { registryQa.fill(HIST("QA/hEtaPr"), track.eta()); @@ -829,7 +834,6 @@ struct HadronNucleiCorrelation { registryQa.fill(HIST("QA/hnSigmaTOFVsPt_Pr_AfterSel"), track.pt() * track.sign(), track.tofNSigmaPr()); registryQa.fill(HIST("QA/hnSigmaTPCVsPt_Pr_AfterSel"), track.pt() * track.sign(), track.tpcNSigmaPr()); registryQa.fill(HIST("QA/hnSigmaITSVsPt_Pr_AfterSel"), track.pt() * track.sign(), track.itsNSigmaPr()); - registryQa.fill(HIST("QA/h2dTPCTOF_Pr_AfterSel"), track.tpcNSigmaPr(), track.tofNSigmaPr()); } if (isDeuteron(track, -1)) { registryQa.fill(HIST("QA/hEtaAntiDe"), track.eta()); @@ -1050,8 +1054,6 @@ struct HadronNucleiCorrelation { registryQa.fill(HIST("QA/hnSigmaTOFVsPt_De"), track.pt() * track.sign(), track.tofNSigmaDe()); registryQa.fill(HIST("QA/hnSigmaITSVsPt_Pr"), track.pt() * track.sign(), track.itsNSigmaPr()); registryQa.fill(HIST("QA/hnSigmaITSVsPt_De"), track.pt() * track.sign(), track.itsNSigmaDe()); - registryQa.fill(HIST("QA/h2dTPCTOF_AntiPr"), track.tpcNSigmaPr(), track.tofNSigmaPr()); - registryQa.fill(HIST("QA/h2dTPCTOF_Pr"), track.tpcNSigmaPr(), track.tofNSigmaPr()); if (isProton(track, -1)) { registryQa.fill(HIST("QA/hEtaAntiPr"), track.eta()); @@ -1059,7 +1061,6 @@ struct HadronNucleiCorrelation { registryQa.fill(HIST("QA/hnSigmaTOFVsPt_Pr_AfterSel"), track.pt() * track.sign(), track.tofNSigmaPr()); registryQa.fill(HIST("QA/hnSigmaTPCVsPt_Pr_AfterSel"), track.pt() * track.sign(), track.tpcNSigmaPr()); registryQa.fill(HIST("QA/hnSigmaITSVsPt_Pr_AfterSel"), track.pt() * track.sign(), track.itsNSigmaPr()); - registryQa.fill(HIST("QA/h2dTPCTOF_AntiPr_AfterSel"), track.tpcNSigmaPr(), track.tofNSigmaPr()); } if (isProton(track, +1)) { registryQa.fill(HIST("QA/hEtaPr"), track.eta()); @@ -1067,7 +1068,6 @@ struct HadronNucleiCorrelation { registryQa.fill(HIST("QA/hnSigmaTOFVsPt_Pr_AfterSel"), track.pt() * track.sign(), track.tofNSigmaPr()); registryQa.fill(HIST("QA/hnSigmaTPCVsPt_Pr_AfterSel"), track.pt() * track.sign(), track.tpcNSigmaPr()); registryQa.fill(HIST("QA/hnSigmaITSVsPt_Pr_AfterSel"), track.pt() * track.sign(), track.itsNSigmaPr()); - registryQa.fill(HIST("QA/h2dTPCTOF_Pr_AfterSel"), track.tpcNSigmaPr(), track.tofNSigmaPr()); } if (isDeuteron(track, -1)) { registryQa.fill(HIST("QA/hEtaAntiDe"), track.eta()); @@ -2031,9 +2031,9 @@ struct HadronNucleiCorrelation { genCaches.reserve(mcCollisions.size()); for (const auto& collision : mcCollisions) { auto particlesPerCol = mcParticles.sliceBy(perMcCollision, collision.globalIndex()); - auto cache = buildGenCollisionCache(particlesPerCol); - registry.fill(HIST("hMult"), cache.mult); - genCaches.emplace(collision.globalIndex(), std::move(cache)); + auto colCache = buildGenCollisionCache(particlesPerCol); + registry.fill(HIST("hMult"), colCache.mult); + genCaches.emplace(collision.globalIndex(), std::move(colCache)); } auto getMultiplicity = [&genCaches](SimCollisions::iterator const& collision) {