From 0b740311493c2d3c6fd0296cf83f0a6bb982d676 Mon Sep 17 00:00:00 2001 From: Nikita Gladin Date: Tue, 21 Jul 2026 14:30:50 +0200 Subject: [PATCH 1/6] PWGLF: add (anti)triton analysis workflow --- PWGLF/Tasks/Nuspex/CMakeLists.txt | 5 + PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx | 451 ++++++++++++++++++++++ 2 files changed, 456 insertions(+) create mode 100644 PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx diff --git a/PWGLF/Tasks/Nuspex/CMakeLists.txt b/PWGLF/Tasks/Nuspex/CMakeLists.txt index 91617ea0567..3803f7ca6ff 100644 --- a/PWGLF/Tasks/Nuspex/CMakeLists.txt +++ b/PWGLF/Tasks/Nuspex/CMakeLists.txt @@ -14,6 +14,11 @@ o2physics_add_dpl_workflow(nuclei-batask PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(antitriton-analysis + SOURCES antitritonAnalysis.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(hypertritonanalysis SOURCES hypertritonAnalysis.cxx PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2Physics::AnalysisCore diff --git a/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx b/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx new file mode 100644 index 00000000000..afbcc8b991f --- /dev/null +++ b/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx @@ -0,0 +1,451 @@ +// 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. +// +/// \brief (Anti)triton analysis +/// \author Nikita Gladin (ngladin@cern.ch) +/// Based on PWGCF/Femto3D/DataModel/singletrackselector.h + +#include "PWGCF/Femto3D/Core/femto3dPairTask.h" +#include "PWGCF/Femto3D/DataModel/PIDutils.h" +#include "PWGCF/Femto3D/DataModel/singletrackselector.h" + +#include "Common/DataModel/Multiplicity.h" + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/DataTypes.h" +#include "Framework/Expressions.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StaticFor.h" +#include "Framework/runDataProcessing.h" +#include "MathUtils/Utils.h" + +#include +#include + +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::soa; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct AntitritonAnalysis { + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry registryTrue{"registryTrue", {}, OutputObjHandlingPolicy::AnalysisObject}; + + Configurable isMC{"isMC", false, ""}; + + Configurable removeSameBunchPileup{"removeSameBunchPileup", false, ""}; + Configurable requestGoodZvtxFT0vsPV{"requestGoodZvtxFT0vsPV", false, ""}; + Configurable requestVertexITSTPC{"requestVertexITSTPC", false, ""}; + Configurable requestVertexTOFmatched{"requestVertexTOFmatched", 0, "0 -> no selection; 1 -> vertex is matched to TOF or TRD; 2 -> matched to both;"}; + Configurable requestNoCollInTimeRangeStandard{"requestNoCollInTimeRangeStandard", false, ""}; + Configurable requestIsGoodITSLayersAll{"requestIsGoodITSLayersAll", false, "cut time intervals with dead ITS staves"}; + Configurable> irCut{"irCut", std::pair{0.f, 100.f}, "[min., max.] IR range to keep events within"}; + Configurable> occupancyCut{"occupancyCut", std::pair{0, 10000}, "[min., max.] occupancy range to keep events within"}; + + Configurable vertexZ{"vertexZ", 10.0, "abs vertexZ value limit"}; + Configurable minP{"minP", 0.0, "lower mometum limit"}; + Configurable maxP{"maxP", 100.0, "upper mometum limit"}; + Configurable eta{"eta", 100.0, "abs eta value limit"}; + Configurable> dcaXY{"dcaXY", std::vector{0.3f, 0.0f, 0.0f}, "abs dcaXY value limit; formula: [0] + [1]*pT^[2]"}; + Configurable> dcaZ{"dcaZ", std::vector{0.3f, 0.0f, 0.0f}, "abs dcaZ value limit; formula: [0] + [1]*pT^[2]"}; + Configurable minTpcNClsFound{"minTpcNClsFound", 0, "minimum allowed number of TPC clasters"}; + Configurable tpcChi2NCl{"tpcChi2NCl", 100.0, "upper limit for chi2 value of a fit over TPC clasters"}; + Configurable tpcCrossedRowsOverFindableCls{"tpcCrossedRowsOverFindableCls", 0, "lower limit of TPC CrossedRows/FindableCls value"}; + Configurable maxTpcFractionSharedCls{"maxTpcFractionSharedCls", 0.4, "maximum fraction of TPC shared clasters"}; + Configurable minItsNCls{"minItsNCls", 0, "minimum allowed number of ITS clasters for a track"}; + Configurable itsChi2NCl{"itsChi2NCl", 100.0, "upper limit for chi2 value of a fit over ITS clasters for a track"}; + Configurable particlePDG{"particlePDG", 1000010030, "PDG code of a particle to perform PID for (only pion, kaon, proton and deurton are supported now)"}; + Configurable> tpcNSigma{"tpcNSigma", std::vector{-4.0f, 4.0f}, "Nsigma range in TPC before the TOF is used"}; + Configurable> itsNSigma{"itsNSigma", std::vector{-10.0f, 10.0f}, "Nsigma range in ITS to use along with TPC"}; + Configurable pidTrshld{"pidTrshld", 0.0, "value of momentum from which the PID is done with TOF (before that only TPC is used)"}; + Configurable massCuttrshld{"massCuttrshld", 0.0, "value of momentum from which the mass cut is done with TOF"}; + Configurable> itsNsigNL{"itsNsigNL", std::vector{-100.0f, 100.0f}, "Nsigma p-dependent cut in ITS ; formula: [0] + [1]*pT"}; + + Configurable> tofNSigma{"tofNSigma", std::vector{-4.0f, 4.0f}, "Nsigma range in TOF"}; + Configurable> tpcNSigmaResidual{"tpcNSigmaResidual", std::vector{-5.0f, 5.0f}, "residual TPC Nsigma cut to use with the TOF"}; + + Configurable> particlePDGtoReject{"particlePDGtoReject", std::vector{2212}, "PDG codes of perticles that will be rejected with TPC"}; + Configurable> rejectWithinNsigmaTOF{"rejectWithinNsigmaTOF", std::vector{-0.0f, 0.0f}, "TOF rejection Nsigma range for particles specified with PDG to be rejected"}; + Configurable> rejectWithinNsigmaTPC{"rejectWithinNsigmaTPC", std::vector{-0.0f, 0.0f}, "TPC rejection Nsigma range for particles specified with PDG to be rejected"}; + + Configurable> centCut{"centCut", std::pair{0.f, 100.f}, "[min., max.] centrality range to keep tracks within"}; + + Configurable> dcaBinning{"dcaBinning", std::vector{501, 0.5f, 1}, "setup for variable binning (geometric progression is used): 1st (int) -- N_bins (must be odd, otherwise will be increased by 1); 2nd (float) -- abs value of the edge of axises in histos (-2nd, +2nd); 3d (int) -- desired ratio between w_bin at the edges and at 0;"}; + Configurable> tofMass{"tofMass", std::vector{3.0f, 3.0f}, "TOF Mass bounds"}; + + std::pair> ITScuts; + std::pair> TPCcuts; + std::pair> TOFcuts; + + static constexpr float kMassTriton = 2.808921f; // GeV/c^2 + + Filter pFilter = o2::aod::singletrackselector::p > minP&& o2::aod::singletrackselector::p < maxP; + Filter etaFilter = nabs(o2::aod::singletrackselector::eta) < eta; + Filter tpcTrkFilter = o2::aod::singletrackselector::tpcNClsFound >= minTpcNClsFound && o2::aod::singletrackselector::unPack(o2::aod::singletrackselector::storedTpcChi2NCl) < tpcChi2NCl && o2::aod::singletrackselector::unPack(o2::aod::singletrackselector::storedTpcCrossedRowsOverFindableCls) > tpcCrossedRowsOverFindableCls; + Filter itsTrkFilter = o2::aod::singletrackselector::unPack(o2::aod::singletrackselector::storedItsChi2NCl) < itsChi2NCl; + Filter vertexFilter = nabs(o2::aod::singletrackselector::posZ) < vertexZ; + + struct HistSet { + std::shared_ptr eta; + std::shared_ptr eta_to_y; + std::shared_ptr y; + std::shared_ptr phi; + std::shared_ptr p; + std::shared_ptr pt; + std::shared_ptr dcaxy_to_p; + std::shared_ptr dcaxy_to_pt; + std::shared_ptr dcaz_to_p; + std::shared_ptr dcaz_to_pt; + std::shared_ptr TPCClusters; + std::shared_ptr ITSClusters; + std::shared_ptr TPCSignal; + std::shared_ptr TOFSignal; + std::shared_ptr mTOF; + std::shared_ptr nsigmaITS; + std::shared_ptr nsigmaTPC; + std::shared_ptr nsigmaTOF; + std::shared_ptr TOFoverTPC; + std::shared_ptr innerParamToP; + std::shared_ptr PtGenPtRec; + std::shared_ptr dcaxy_dcaz_to_pt; + std::shared_ptr dcaxy_to_dcaz; + std::shared_ptr origin; + }; + + const std::vector stageDirs = { + "init", + "No_Cuts", + "ITS_Cuts", + "TPC_Cuts", + "TOF_Cuts", + "ITSTPC_Cut", + "PID_Cuts", + "TOFmass_Cut", + "Rejection_Cut", + "TPCLinear_Cut", + }; + + // signDirs[0] = "t" for sign > 0 (triton), signDirs[1] = "at" for sign < 0 (antitriton). + const std::array signDirs = {"t", "at"}; + + std::vector> hSets; + std::vector> hSetsTrue; + + HistSet makeHistSet(HistogramRegistry& reg, const std::string& dir, int pdgForPid = 0) + { + HistSet h; + + h.eta = reg.add((dir + "/eta").c_str(), "#eta;#eta;Entries", kTH1F, {{200, -2.5, 2.5}}); + h.y = reg.add((dir + "/y").c_str(), "y;y;Entries", kTH1F, {{200, -2.5, 2.5}}); + h.eta_to_y = reg.add((dir + "/eta_to_y").c_str(), "#eta;y;Entries", kTH2F, {{200, -2.5, 2.5}, {200, -2.5, 2.5}}); + h.phi = reg.add((dir + "/phi").c_str(), "#phi;#phi;Entries", kTH1F, {{200, 0., 2. * M_PI}}); + h.p = reg.add((dir + "/p").c_str(), "p;p (GeV/#it{c});Entries", kTH1F, {{100, 0., 5.}}); + h.pt = reg.add((dir + "/pt").c_str(), "p_{T};p_{T} (GeV/#it{c});Entries", kTH1F, {{100, 0., 5.}}); + h.dcaxy_to_p = reg.add((dir + "/dcaxy_to_p").c_str(), "DCA_{xy} vs p;p (GeV/#it{c});DCA_{xy} (cm)", kTH2F, {{100, 0., 5.0}, {501, -0.5, 0.5}}); + h.dcaxy_to_pt = reg.add((dir + "/dcaxy_to_pt").c_str(), "DCA_{xy} vs p_{T};p_{T} (GeV/#it{c});DCA_{xy} (cm)", kTH2F, {{100, 0., 5.0}, {501, -0.5, 0.5}}); + h.dcaz_to_p = reg.add((dir + "/dcaz_to_p").c_str(), "DCA_{z} vs p;p (GeV/#it{c});DCA_{z} (cm)", kTH2F, {{100, 0., 5.0}, {501, -0.5, 0.5}}); + h.dcaz_to_pt = reg.add((dir + "/dcaz_to_pt").c_str(), "DCA_{z} vs p_{T};p_{T} (GeV/#it{c});DCA_{z} (cm)", kTH2F, {{100, 0., 5.0}, {501, -0.5, 0.5}}); + h.TPCClusters = reg.add((dir + "/TPCClusters").c_str(), "TPC Clusters;N_{TPC clusters};Entries", kTH1F, {{163, -0.5, 162.5}}); + h.ITSClusters = reg.add((dir + "/ITSClusters").c_str(), "ITS Clusters;N_{ITS clusters};Entries", kTH1F, {{10, -0.5, 9.5}}); + h.TPCSignal = reg.add((dir + "/TPCSignal").c_str(), "TPC Signal;#it{p}_{inner} (GeV/#it{c});dE/dx in TPC (arbitrary units)", kTH2F, {{200, 0., 5.0}, {1000, 0., 1000.0}}); + h.TOFSignal = reg.add((dir + "/TOFSignal").c_str(), "TOF Signal;#it{p} (GeV/#it{c});#beta", kTH2F, {{200, 0., 5.0}, {100, 0., 1.5}}); + h.mTOF = reg.add((dir + "/mTOF").c_str(), "m_{TOF};p_{T} (GeV/#it{c});m_{TOF}(GeV/#it{c}^{2})", kTH2F, {{120, 0., 6.}, {1000, -1.5, 5.0}}); + h.innerParamToP = reg.add((dir + "/ip_to_p").c_str(), ";#it{p} (GeV/#it{c});ip_to_p", kTH2F, {{100, 0., 5.0}, {100, 0.0, 2.0}}); + h.PtGenPtRec = reg.add((dir + "/ptgenptrec").c_str(), ";#it{p_{T, rec}} (GeV/#it{c});#it{p_{T, rec}} - #it{p_{T, gen}}(GeV/#it{c})", kTH2F, {{100, 0., 5.0}, {100, -2.5, 2.5}}); + h.dcaxy_dcaz_to_pt = reg.add( + (dir + "/dcaxy_dcaz_to_pt").c_str(), + "DCA_{xy} vs DCA_{z} vs p_{T};DCA_{xy} (cm);DCA_{z} (cm);p_{T} (GeV/#it{c})", + kTH3F, + { + {101, -0.5, 0.5}, // x axis: DCA_xy + {101, -0.5, 0.5}, // y axis: DCA_z + {20, 0., 5.0} // z axis: pT + }); + h.dcaxy_to_dcaz = reg.add( + (dir + "/dcaxy_to_dcaz").c_str(), + "DCA_{z} vs DCA_{xy};DCA_{xy} (cm);DCA_{z} (cm);Counts", + kTH2F, + { + {501, -0.5, 0.5}, // x axis: DCAxy + {501, -0.5, 0.5} // y axis: DCAz + }); + h.origin = reg.add((dir + "/origin").c_str(), "MC origin;origin (-1: unmatched, 0: primary, 1: weak decay, 2: material);Entries", kTH1F, {{4, -1.5, 2.5}}); + + if (pdgForPid != 0) { + h.TOFoverTPC = reg.add((dir + Form("/TOFoverTPC_PDG%i", pdgForPid)).c_str(), "n#sigma_{TOF};n#sigma_{TPC};", kTH2F, {{100, -10., 10.}, {100, -10., 10.}}); + h.nsigmaITS = reg.add((dir + Form("/nsigmaITS_PDG%i", pdgForPid)).c_str(), Form("n#sigma_{ITS};p (GeV/#it{c});n#sigma_{ITS}"), kTH2F, {{100, 0., 5.}, {100, -10., 10.}}); + h.nsigmaTPC = reg.add((dir + Form("/nsigmaTPC_PDG%i", pdgForPid)).c_str(), Form("n#sigma_{TPC};p (GeV/#it{c});n#sigma_{TPC}"), kTH2F, {{100, 0., 5.}, {100, -10., 10.}}); + h.nsigmaTOF = reg.add((dir + Form("/nsigmaTOF_PDG%i", pdgForPid)).c_str(), Form("n#sigma_{TOF};p (GeV/#it{c});n#sigma_{TOF}"), kTH2F, {{100, 0., 5.}, {100, -10., 10.}}); + } + + return h; + } + + template + static float getMTOF(const TrackType& track) + { + const float beta = track.beta(); + if (beta <= 0.f || beta >= 1.f) { + return -1.f; + } + return track.p() * std::sqrt(1.f / (beta * beta) - 1.f); + } + + template + static float getY(const TrackType& track, float mass) + { + const float pTr = track.p(); + const float pzTr = track.pz(); + const float ETr = std::sqrt(pTr * pTr + mass * mass); + return 0.5f * std::log((ETr + pzTr) / (ETr - pzTr)); + } + + template + void fillHistSet(HistSet& h, const TrackType& track, int pdg) + { + const float mass = kMassTriton; + h.eta->Fill(track.eta()); + h.eta_to_y->Fill(track.eta(), getY(track, mass)); + h.y->Fill(getY(track, mass)); + h.phi->Fill(track.phi()); + h.p->Fill(track.p()); + h.pt->Fill(track.pt()); + h.dcaxy_to_p->Fill(track.p(), track.dcaXY()); + h.dcaxy_to_pt->Fill(track.pt(), track.dcaXY()); + h.dcaz_to_p->Fill(track.p(), track.dcaZ()); + h.dcaz_to_pt->Fill(track.pt(), track.dcaZ()); + h.dcaxy_dcaz_to_pt->Fill(track.dcaXY(), track.dcaZ(), track.pt()); + h.dcaxy_to_dcaz->Fill(track.dcaXY(), track.dcaZ()); + h.TPCClusters->Fill(track.tpcNClsFound()); + h.ITSClusters->Fill(track.itsNCls()); + h.nsigmaITS->Fill(track.p(), o2::aod::singletrackselector::getITSNsigma(track, pdg)); + h.nsigmaTPC->Fill(track.p(), o2::aod::singletrackselector::getTPCNsigma(track, pdg)); + h.nsigmaTOF->Fill(track.p(), o2::aod::singletrackselector::getTOFNsigma(track, pdg)); + h.TOFoverTPC->Fill(o2::aod::singletrackselector::getTPCNsigma(track, pdg), o2::aod::singletrackselector::getTOFNsigma(track, pdg)); + } + + template + void fillHistSetExtra(HistSet& h, const TrackType& track, int pdg) + { + h.TPCSignal->Fill(track.tpcInnerParam(), track.tpcSignal()); + h.TOFSignal->Fill(track.p(), track.beta()); + h.mTOF->Fill(track.pt(), getMTOF(track)); + h.innerParamToP->Fill(track.p(), track.tpcInnerParam() / track.p()); + if constexpr (HasMC) + h.PtGenPtRec->Fill(track.pt(), track.pt() - track.pt_MC()); + } + + template + void fillSet(HistSet& Set, HistSet& mcSet, const TrackType& track, int pdg) + { + fillHistSet(Set, track, pdg); + if constexpr (FillExtra) { + fillHistSetExtra(Set, track, pdg); + } + + if constexpr (HasMC) { + if ((std::abs(track.pdgCode()) == pdg) && (track.pdgCode() / std::abs(track.pdgCode()) == track.sign())) { + mcSet.origin->Fill(track.origin()); + fillHistSet(mcSet, track, pdg); + if constexpr (FillExtra) { + fillHistSetExtra(mcSet, track, pdg); + } + } + } + } + + void init(o2::framework::InitContext&) + { + + if (isMC.value) + o2::aod::ITSResponse::setMCDefaultParameters(); // set MC parametrisation for the ITS PID + + ITScuts = std::make_pair(particlePDG.value, itsNSigma); + TPCcuts = std::make_pair(particlePDG.value, tpcNSigma); + TOFcuts = std::make_pair(particlePDG.value, tofNSigma); + + int N = dcaBinning.value[0]; // number of bins -- must be odd otherwise will be increased by 1 + if (N % 2 != 1) { + N += 1; + } + + std::unique_ptr dca_bins; + if (static_cast(dcaBinning.value[2]) != 1.0) { + dca_bins = calc_var_bins(N + 1, dcaBinning.value[1], static_cast(dcaBinning.value[2])); + } else { + dca_bins = calc_const_bins(N, -dcaBinning.value[1], dcaBinning.value[1]); + } + auto const_bins_p = calc_const_bins(100, 0., 5.0); + + hSets.resize(stageDirs.size()); + hSetsTrue.resize(stageDirs.size()); + for (size_t i = 0; i < stageDirs.size(); i++) { + for (size_t s = 0; s < signDirs.size(); s++) { + const std::string dir = stageDirs[i] + "/" + signDirs[s]; + hSets[i][s] = makeHistSet(registry, dir, particlePDG.value); + hSetsTrue[i][s] = makeHistSet(registryTrue, dir + "/true", particlePDG.value); + } + } + + const AxisSpec axisMult{5001, -0.5, 5000.5, "mult."}; + const AxisSpec axisPerc{101, -0.5, 100.5, "percentile"}; + registry.add("posZ", "posZ", kTH1F, {{300, -16., 16., "posZ"}}); + registry.add("mult", "mult", kTH1F, {axisMult}); + registry.add("MultVsCent", "MultVsCent", kTH2F, {axisMult, axisPerc}); + registry.add("IRvsOccupancy", "IRvsOccupancy", kTH2I, {{10000, 0, 10000, "Occupancy"}, {50, 0, 50, "IR, kHz"}}); + } + + template + void fillHistograms(ColsType const& collisions, TracksType const& tracks) + { + for (const auto& track : tracks) { + const int signIdx = (-track.sign() + 1) / 2; // 0: triton, 1: antitriton + fillSet(hSets[1][signIdx], hSetsTrue[1][signIdx], track, particlePDG.value); // nocuts + } + for (const auto& collision : collisions) { + if (removeSameBunchPileup && !collision.isNoSameBunchPileup()) + continue; + if (requestGoodZvtxFT0vsPV && !collision.isGoodZvtxFT0vsPV()) + continue; + if (requestVertexITSTPC && !collision.isVertexITSTPC()) + continue; + if (requestVertexTOFmatched > collision.isVertexTOForTRDmatched()) + continue; + if (requestNoCollInTimeRangeStandard && !collision.noCollInTimeRangeStandard()) + continue; + if (requestIsGoodITSLayersAll && !collision.isGoodITSLayersAll()) + continue; + if (collision.multPerc() < centCut.value.first || collision.multPerc() >= centCut.value.second) + continue; + if (collision.hadronicRate() < irCut.value.first || collision.hadronicRate() >= irCut.value.second) + continue; + if (collision.occupancy() < occupancyCut.value.first || collision.occupancy() >= occupancyCut.value.second) + continue; + + registry.fill(HIST("posZ"), collision.posZ()); + registry.fill(HIST("mult"), collision.mult()); + registry.fill(HIST("MultVsCent"), collision.mult(), collision.multPerc()); + registry.fill(HIST("IRvsOccupancy"), collision.occupancy(), collision.hadronicRate()); + } + int cnt = 0; + for (const auto& track : tracks) { + const auto& coll = track.template singleCollSel_as(); + const int signIdx = (-track.sign() + 1) / 2; // 0: triton, 1: antitriton + + if (removeSameBunchPileup && !coll.isNoSameBunchPileup()) + continue; + if (requestGoodZvtxFT0vsPV && !coll.isGoodZvtxFT0vsPV()) + continue; + if (requestVertexITSTPC && !coll.isVertexITSTPC()) + continue; + if (requestVertexTOFmatched > coll.isVertexTOForTRDmatched()) + continue; + if (requestNoCollInTimeRangeStandard && !coll.noCollInTimeRangeStandard()) + continue; + if (requestIsGoodITSLayersAll && !coll.isGoodITSLayersAll()) + continue; + if (std::fabs(coll.posZ()) > vertexZ) + continue; + if (coll.multPerc() < centCut.value.first || coll.multPerc() >= centCut.value.second) + continue; + if (coll.hadronicRate() < irCut.value.first || coll.hadronicRate() >= irCut.value.second) + continue; + if (coll.occupancy() < occupancyCut.value.first || coll.occupancy() >= occupancyCut.value.second) + continue; + if (track.tpcFractionSharedCls() > maxTpcFractionSharedCls) + continue; + if (track.itsNCls() < minItsNCls) + continue; + if (std::fabs(track.dcaXY()) > dcaXY.value[0] + dcaXY.value[1] * std::pow(track.pt(), dcaXY.value[2])) + continue; + if (std::fabs(track.dcaZ()) > dcaZ.value[0] + dcaZ.value[1] * std::pow(track.pt(), dcaZ.value[2])) + continue; + + if (o2::aod::singletrackselector::ITSselection(track, ITScuts)) { + fillSet(hSets[2][signIdx], hSetsTrue[2][signIdx], track, particlePDG.value); // ITSCuts + } + if (o2::aod::singletrackselector::TPCselection(track, TPCcuts, itsNSigma.value)) { + fillSet(hSets[3][signIdx], hSetsTrue[3][signIdx], track, particlePDG.value); // TPCCuts + } + if (o2::aod::singletrackselector::TOFselection(track, TOFcuts, tpcNSigmaResidual.value)) { + fillSet(hSets[4][signIdx], hSetsTrue[4][signIdx], track, particlePDG.value); // TOFCuts + } + if (o2::aod::singletrackselector::TPCselection(track, TPCcuts, itsNSigma.value)) { + fillSet(hSets[5][signIdx], hSetsTrue[5][signIdx], track, particlePDG.value); // ITSTPC + } + + const bool pidOk = + (track.p() < pidTrshld) + ? o2::aod::singletrackselector::TPCselection(track, TPCcuts, itsNSigma.value) + : o2::aod::singletrackselector::TPCselection(track, std::make_pair(particlePDG.value, tpcNSigmaResidual.value), tpcNSigmaResidual.value); + if (!pidOk) + continue; + if (std::fabs(getY(track, kMassTriton)) > eta) + continue; + + fillSet(hSets[6][signIdx], hSetsTrue[6][signIdx], track, particlePDG.value); // PIDcuts + if constexpr (FillExtra) { + if (track.p() >= massCuttrshld && (getMTOF(track) <= tofMass.value[0] || getMTOF(track) >= tofMass.value[1])) { + continue; + } + } + fillSet(hSets[7][signIdx], hSetsTrue[7][signIdx], track, particlePDG.value); // masscut + + bool rejectedByPDG = false; + for (const int& pdgToReject : particlePDGtoReject.value) { + if (o2::aod::singletrackselector::TPCselection(track, std::make_pair(pdgToReject, rejectWithinNsigmaTPC.value))) { + rejectedByPDG = true; + break; + } + } + if (rejectedByPDG) + continue; + fillSet(hSets[8][signIdx], hSetsTrue[8][signIdx], track, particlePDG.value); // rd + + if (getITSNsigma(track, particlePDG.value) <= itsNsigNL.value[0] + itsNsigNL.value[1] * track.p()) { + continue; + } + fillSet(hSets[9][signIdx], hSetsTrue[9][signIdx], track, particlePDG.value); // nl + } + } + + void processDefault(soa::Filtered> const& collisions, soa::Filtered> const& tracks) + { + fillHistograms(collisions, tracks); + } + PROCESS_SWITCH(AntitritonAnalysis, processDefault, "process default", true); + + void processExtra(soa::Filtered> const& collisions, soa::Filtered> const& tracks) + { + fillHistograms(collisions, tracks); + } + PROCESS_SWITCH(AntitritonAnalysis, processExtra, "process extra", false); + + void processMC(soa::Filtered> const& collisions, soa::Filtered> const& tracks) + { + fillHistograms(collisions, tracks); + } + PROCESS_SWITCH(AntitritonAnalysis, processMC, "process MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} From 6a1bbccce0a0c7e9af159154ac7256ae593d8131 Mon Sep 17 00:00:00 2001 From: Nikita Gladin Date: Tue, 21 Jul 2026 15:15:51 +0200 Subject: [PATCH 2/6] PWGLF antitriton workflow formatting fix --- PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx | 26 +++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx b/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx index afbcc8b991f..dc9425915fd 100644 --- a/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx +++ b/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx @@ -19,15 +19,15 @@ #include "Common/DataModel/Multiplicity.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/Expressions.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StaticFor.h" -#include "Framework/runDataProcessing.h" -#include "MathUtils/Utils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -242,7 +242,7 @@ struct AntitritonAnalysis { } template - void fillHistSetExtra(HistSet& h, const TrackType& track, int pdg) + void fillHistSetExtra(HistSet& h, const TrackType& track) { h.TPCSignal->Fill(track.tpcInnerParam(), track.tpcSignal()); h.TOFSignal->Fill(track.p(), track.beta()); @@ -257,7 +257,7 @@ struct AntitritonAnalysis { { fillHistSet(Set, track, pdg); if constexpr (FillExtra) { - fillHistSetExtra(Set, track, pdg); + fillHistSetExtra(Set, track); } if constexpr (HasMC) { @@ -265,7 +265,7 @@ struct AntitritonAnalysis { mcSet.origin->Fill(track.origin()); fillHistSet(mcSet, track, pdg); if constexpr (FillExtra) { - fillHistSetExtra(mcSet, track, pdg); + fillHistSetExtra(mcSet, track); } } } @@ -344,7 +344,7 @@ struct AntitritonAnalysis { registry.fill(HIST("MultVsCent"), collision.mult(), collision.multPerc()); registry.fill(HIST("IRvsOccupancy"), collision.occupancy(), collision.hadronicRate()); } - int cnt = 0; + for (const auto& track : tracks) { const auto& coll = track.template singleCollSel_as(); const int signIdx = (-track.sign() + 1) / 2; // 0: triton, 1: antitriton From 890b1bd98eb47c37f97d4c2037b98ad3d4d9666c Mon Sep 17 00:00:00 2001 From: Nikita Gladin Date: Thu, 23 Jul 2026 18:36:56 +0200 Subject: [PATCH 3/6] PWGLF antitriton workflow review fix --- PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx | 49 ++++++++++++----------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx b/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx index dc9425915fd..a53b3e51290 100644 --- a/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx +++ b/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx @@ -17,22 +17,31 @@ #include "PWGCF/Femto3D/DataModel/PIDutils.h" #include "PWGCF/Femto3D/DataModel/singletrackselector.h" -#include "Common/DataModel/Multiplicity.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/PIDResponseITS.h" +#include #include #include #include -#include +#include #include #include -#include +#include +#include +#include #include -#include -#include -#include +#include +#include +#include +#include +#include #include +#include +#include +#include #include #include #include @@ -71,7 +80,7 @@ struct AntitritonAnalysis { Configurable maxTpcFractionSharedCls{"maxTpcFractionSharedCls", 0.4, "maximum fraction of TPC shared clasters"}; Configurable minItsNCls{"minItsNCls", 0, "minimum allowed number of ITS clasters for a track"}; Configurable itsChi2NCl{"itsChi2NCl", 100.0, "upper limit for chi2 value of a fit over ITS clasters for a track"}; - Configurable particlePDG{"particlePDG", 1000010030, "PDG code of a particle to perform PID for (only pion, kaon, proton and deurton are supported now)"}; + Configurable particlePDG{"particlePDG", o2::constants::physics::Pdg::kTriton, "PDG code of a particle to perform PID for"}; Configurable> tpcNSigma{"tpcNSigma", std::vector{-4.0f, 4.0f}, "Nsigma range in TPC before the TOF is used"}; Configurable> itsNSigma{"itsNSigma", std::vector{-10.0f, 10.0f}, "Nsigma range in ITS to use along with TPC"}; Configurable pidTrshld{"pidTrshld", 0.0, "value of momentum from which the PID is done with TOF (before that only TPC is used)"}; @@ -81,7 +90,7 @@ struct AntitritonAnalysis { Configurable> tofNSigma{"tofNSigma", std::vector{-4.0f, 4.0f}, "Nsigma range in TOF"}; Configurable> tpcNSigmaResidual{"tpcNSigmaResidual", std::vector{-5.0f, 5.0f}, "residual TPC Nsigma cut to use with the TOF"}; - Configurable> particlePDGtoReject{"particlePDGtoReject", std::vector{2212}, "PDG codes of perticles that will be rejected with TPC"}; + Configurable> particlePDGtoReject{"particlePDGtoReject", std::vector{PDG_t::kProton}, "PDG codes of perticles that will be rejected with TPC"}; Configurable> rejectWithinNsigmaTOF{"rejectWithinNsigmaTOF", std::vector{-0.0f, 0.0f}, "TOF rejection Nsigma range for particles specified with PDG to be rejected"}; Configurable> rejectWithinNsigmaTPC{"rejectWithinNsigmaTPC", std::vector{-0.0f, 0.0f}, "TPC rejection Nsigma range for particles specified with PDG to be rejected"}; @@ -94,7 +103,7 @@ struct AntitritonAnalysis { std::pair> TPCcuts; std::pair> TOFcuts; - static constexpr float kMassTriton = 2.808921f; // GeV/c^2 + static constexpr float kMassTriton = o2::constants::physics::MassTriton; // GeV/c^2 Filter pFilter = o2::aod::singletrackselector::p > minP&& o2::aod::singletrackselector::p < maxP; Filter etaFilter = nabs(o2::aod::singletrackselector::eta) < eta; @@ -129,7 +138,7 @@ struct AntitritonAnalysis { std::shared_ptr origin; }; - const std::vector stageDirs = { + static inline const std::vector stageDirs = { "init", "No_Cuts", "ITS_Cuts", @@ -143,7 +152,7 @@ struct AntitritonAnalysis { }; // signDirs[0] = "t" for sign > 0 (triton), signDirs[1] = "at" for sign < 0 (antitriton). - const std::array signDirs = {"t", "at"}; + static inline const std::array signDirs = {"t", "at"}; std::vector> hSets; std::vector> hSetsTrue; @@ -208,22 +217,14 @@ struct AntitritonAnalysis { return track.p() * std::sqrt(1.f / (beta * beta) - 1.f); } - template - static float getY(const TrackType& track, float mass) - { - const float pTr = track.p(); - const float pzTr = track.pz(); - const float ETr = std::sqrt(pTr * pTr + mass * mass); - return 0.5f * std::log((ETr + pzTr) / (ETr - pzTr)); - } - template void fillHistSet(HistSet& h, const TrackType& track, int pdg) { const float mass = kMassTriton; + const auto y = static_cast(RecoDecay::y(std::array{track.px(), track.py(), track.pz()}, mass)); h.eta->Fill(track.eta()); - h.eta_to_y->Fill(track.eta(), getY(track, mass)); - h.y->Fill(getY(track, mass)); + h.eta_to_y->Fill(track.eta(), y); + h.y->Fill(y); h.phi->Fill(track.phi()); h.p->Fill(track.p()); h.pt->Fill(track.pt()); @@ -281,7 +282,7 @@ struct AntitritonAnalysis { TPCcuts = std::make_pair(particlePDG.value, tpcNSigma); TOFcuts = std::make_pair(particlePDG.value, tofNSigma); - int N = dcaBinning.value[0]; // number of bins -- must be odd otherwise will be increased by 1 + int N = static_cast(dcaBinning.value[0]); // number of bins -- must be odd otherwise will be increased by 1 if (N % 2 != 1) { N += 1; } @@ -397,7 +398,7 @@ struct AntitritonAnalysis { : o2::aod::singletrackselector::TPCselection(track, std::make_pair(particlePDG.value, tpcNSigmaResidual.value), tpcNSigmaResidual.value); if (!pidOk) continue; - if (std::fabs(getY(track, kMassTriton)) > eta) + if (std::fabs(static_cast(RecoDecay::y(std::array{track.px(), track.py(), track.pz()}, kMassTriton))) > eta) continue; fillSet(hSets[6][signIdx], hSetsTrue[6][signIdx], track, particlePDG.value); // PIDcuts From 53d0a1a9a747e5074c19e7f82468698f85d9c7c9 Mon Sep 17 00:00:00 2001 From: Nikita Gladin Date: Mon, 27 Jul 2026 02:51:55 +0200 Subject: [PATCH 4/6] PWGLF antitriton refactoring and formatting fix --- PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx | 239 ++++++++++++---------- 1 file changed, 135 insertions(+), 104 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx b/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx index a53b3e51290..7e40b097951 100644 --- a/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx +++ b/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx @@ -9,9 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // -/// \brief (Anti)triton analysis -/// \author Nikita Gladin (ngladin@cern.ch) -/// Based on PWGCF/Femto3D/DataModel/singletrackselector.h + +/// \file antitritonAnalysis.cxx +/// \brief Analysis of (anti)tritons, based on PWGCF/Femto3D/DataModel/singletrackselector.h +/// \author Nikita Gladin #include "PWGCF/Femto3D/Core/femto3dPairTask.h" #include "PWGCF/Femto3D/DataModel/PIDutils.h" @@ -20,6 +21,7 @@ #include "Common/Core/RecoDecay.h" #include "Common/DataModel/PIDResponseITS.h" +#include #include #include #include @@ -29,6 +31,7 @@ #include #include #include +#include #include #include @@ -57,6 +60,9 @@ struct AntitritonAnalysis { HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry registryTrue{"registryTrue", {}, OutputObjHandlingPolicy::AnalysisObject}; + Service pdgDB; + float particleMass = 0.f; + Configurable isMC{"isMC", false, ""}; Configurable removeSameBunchPileup{"removeSameBunchPileup", false, ""}; @@ -72,6 +78,7 @@ struct AntitritonAnalysis { Configurable minP{"minP", 0.0, "lower mometum limit"}; Configurable maxP{"maxP", 100.0, "upper mometum limit"}; Configurable eta{"eta", 100.0, "abs eta value limit"}; + Configurable y{"y", 100.0, "abs y value limit"}; Configurable> dcaXY{"dcaXY", std::vector{0.3f, 0.0f, 0.0f}, "abs dcaXY value limit; formula: [0] + [1]*pT^[2]"}; Configurable> dcaZ{"dcaZ", std::vector{0.3f, 0.0f, 0.0f}, "abs dcaZ value limit; formula: [0] + [1]*pT^[2]"}; Configurable minTpcNClsFound{"minTpcNClsFound", 0, "minimum allowed number of TPC clasters"}; @@ -99,11 +106,9 @@ struct AntitritonAnalysis { Configurable> dcaBinning{"dcaBinning", std::vector{501, 0.5f, 1}, "setup for variable binning (geometric progression is used): 1st (int) -- N_bins (must be odd, otherwise will be increased by 1); 2nd (float) -- abs value of the edge of axises in histos (-2nd, +2nd); 3d (int) -- desired ratio between w_bin at the edges and at 0;"}; Configurable> tofMass{"tofMass", std::vector{3.0f, 3.0f}, "TOF Mass bounds"}; - std::pair> ITScuts; - std::pair> TPCcuts; - std::pair> TOFcuts; - - static constexpr float kMassTriton = o2::constants::physics::MassTriton; // GeV/c^2 + std::pair> itsCuts; + std::pair> tpcCuts; + std::pair> tofCuts; Filter pFilter = o2::aod::singletrackselector::p > minP&& o2::aod::singletrackselector::p < maxP; Filter etaFilter = nabs(o2::aod::singletrackselector::eta) < eta; @@ -113,28 +118,28 @@ struct AntitritonAnalysis { struct HistSet { std::shared_ptr eta; - std::shared_ptr eta_to_y; + std::shared_ptr etaToY; std::shared_ptr y; std::shared_ptr phi; std::shared_ptr p; std::shared_ptr pt; - std::shared_ptr dcaxy_to_p; - std::shared_ptr dcaxy_to_pt; - std::shared_ptr dcaz_to_p; - std::shared_ptr dcaz_to_pt; - std::shared_ptr TPCClusters; - std::shared_ptr ITSClusters; - std::shared_ptr TPCSignal; - std::shared_ptr TOFSignal; - std::shared_ptr mTOF; + std::shared_ptr dcaxyToP; + std::shared_ptr dcaxyToPt; + std::shared_ptr dcazToP; + std::shared_ptr dcazToPt; + std::shared_ptr tpcClusters; + std::shared_ptr itsClusters; + std::shared_ptr tpcSignal; + std::shared_ptr tofSignal; + std::shared_ptr massTOF; std::shared_ptr nsigmaITS; std::shared_ptr nsigmaTPC; std::shared_ptr nsigmaTOF; - std::shared_ptr TOFoverTPC; + std::shared_ptr tofOverTPC; std::shared_ptr innerParamToP; - std::shared_ptr PtGenPtRec; - std::shared_ptr dcaxy_dcaz_to_pt; - std::shared_ptr dcaxy_to_dcaz; + std::shared_ptr ptGenPtRec; + std::shared_ptr dcaxyDcazToPt; + std::shared_ptr dcaxyToDcaz; std::shared_ptr origin; }; @@ -163,22 +168,22 @@ struct AntitritonAnalysis { h.eta = reg.add((dir + "/eta").c_str(), "#eta;#eta;Entries", kTH1F, {{200, -2.5, 2.5}}); h.y = reg.add((dir + "/y").c_str(), "y;y;Entries", kTH1F, {{200, -2.5, 2.5}}); - h.eta_to_y = reg.add((dir + "/eta_to_y").c_str(), "#eta;y;Entries", kTH2F, {{200, -2.5, 2.5}, {200, -2.5, 2.5}}); - h.phi = reg.add((dir + "/phi").c_str(), "#phi;#phi;Entries", kTH1F, {{200, 0., 2. * M_PI}}); + h.etaToY = reg.add((dir + "/eta_to_y").c_str(), "#eta;y;Entries", kTH2F, {{200, -2.5, 2.5}, {200, -2.5, 2.5}}); + h.phi = reg.add((dir + "/phi").c_str(), "#phi;#phi;Entries", kTH1F, {{200, 0., o2::constants::math::TwoPI}}); h.p = reg.add((dir + "/p").c_str(), "p;p (GeV/#it{c});Entries", kTH1F, {{100, 0., 5.}}); h.pt = reg.add((dir + "/pt").c_str(), "p_{T};p_{T} (GeV/#it{c});Entries", kTH1F, {{100, 0., 5.}}); - h.dcaxy_to_p = reg.add((dir + "/dcaxy_to_p").c_str(), "DCA_{xy} vs p;p (GeV/#it{c});DCA_{xy} (cm)", kTH2F, {{100, 0., 5.0}, {501, -0.5, 0.5}}); - h.dcaxy_to_pt = reg.add((dir + "/dcaxy_to_pt").c_str(), "DCA_{xy} vs p_{T};p_{T} (GeV/#it{c});DCA_{xy} (cm)", kTH2F, {{100, 0., 5.0}, {501, -0.5, 0.5}}); - h.dcaz_to_p = reg.add((dir + "/dcaz_to_p").c_str(), "DCA_{z} vs p;p (GeV/#it{c});DCA_{z} (cm)", kTH2F, {{100, 0., 5.0}, {501, -0.5, 0.5}}); - h.dcaz_to_pt = reg.add((dir + "/dcaz_to_pt").c_str(), "DCA_{z} vs p_{T};p_{T} (GeV/#it{c});DCA_{z} (cm)", kTH2F, {{100, 0., 5.0}, {501, -0.5, 0.5}}); - h.TPCClusters = reg.add((dir + "/TPCClusters").c_str(), "TPC Clusters;N_{TPC clusters};Entries", kTH1F, {{163, -0.5, 162.5}}); - h.ITSClusters = reg.add((dir + "/ITSClusters").c_str(), "ITS Clusters;N_{ITS clusters};Entries", kTH1F, {{10, -0.5, 9.5}}); - h.TPCSignal = reg.add((dir + "/TPCSignal").c_str(), "TPC Signal;#it{p}_{inner} (GeV/#it{c});dE/dx in TPC (arbitrary units)", kTH2F, {{200, 0., 5.0}, {1000, 0., 1000.0}}); - h.TOFSignal = reg.add((dir + "/TOFSignal").c_str(), "TOF Signal;#it{p} (GeV/#it{c});#beta", kTH2F, {{200, 0., 5.0}, {100, 0., 1.5}}); - h.mTOF = reg.add((dir + "/mTOF").c_str(), "m_{TOF};p_{T} (GeV/#it{c});m_{TOF}(GeV/#it{c}^{2})", kTH2F, {{120, 0., 6.}, {1000, -1.5, 5.0}}); + h.dcaxyToP = reg.add((dir + "/dcaxy_to_p").c_str(), "DCA_{xy} vs p;p (GeV/#it{c});DCA_{xy} (cm)", kTH2F, {{100, 0., 5.0}, {501, -0.5, 0.5}}); + h.dcaxyToPt = reg.add((dir + "/dcaxy_to_pt").c_str(), "DCA_{xy} vs p_{T};p_{T} (GeV/#it{c});DCA_{xy} (cm)", kTH2F, {{100, 0., 5.0}, {501, -0.5, 0.5}}); + h.dcazToP = reg.add((dir + "/dcaz_to_p").c_str(), "DCA_{z} vs p;p (GeV/#it{c});DCA_{z} (cm)", kTH2F, {{100, 0., 5.0}, {501, -0.5, 0.5}}); + h.dcazToPt = reg.add((dir + "/dcaz_to_pt").c_str(), "DCA_{z} vs p_{T};p_{T} (GeV/#it{c});DCA_{z} (cm)", kTH2F, {{100, 0., 5.0}, {501, -0.5, 0.5}}); + h.tpcClusters = reg.add((dir + "/TPCClusters").c_str(), "TPC Clusters;N_{TPC clusters};Entries", kTH1F, {{163, -0.5, 162.5}}); + h.itsClusters = reg.add((dir + "/ITSClusters").c_str(), "ITS Clusters;N_{ITS clusters};Entries", kTH1F, {{10, -0.5, 9.5}}); + h.tpcSignal = reg.add((dir + "/TPCSignal").c_str(), "TPC Signal;#it{p}_{inner} (GeV/#it{c});dE/dx in TPC (arbitrary units)", kTH2F, {{200, 0., 5.0}, {1000, 0., 1000.0}}); + h.tofSignal = reg.add((dir + "/TOFSignal").c_str(), "TOF Signal;#it{p} (GeV/#it{c});#beta", kTH2F, {{200, 0., 5.0}, {100, 0., 1.5}}); + h.massTOF = reg.add((dir + "/mTOF").c_str(), "m_{TOF};p_{T} (GeV/#it{c});m_{TOF}(GeV/#it{c}^{2})", kTH2F, {{120, 0., 6.}, {1000, -1.5, 5.0}}); h.innerParamToP = reg.add((dir + "/ip_to_p").c_str(), ";#it{p} (GeV/#it{c});ip_to_p", kTH2F, {{100, 0., 5.0}, {100, 0.0, 2.0}}); - h.PtGenPtRec = reg.add((dir + "/ptgenptrec").c_str(), ";#it{p_{T, rec}} (GeV/#it{c});#it{p_{T, rec}} - #it{p_{T, gen}}(GeV/#it{c})", kTH2F, {{100, 0., 5.0}, {100, -2.5, 2.5}}); - h.dcaxy_dcaz_to_pt = reg.add( + h.ptGenPtRec = reg.add((dir + "/ptgenptrec").c_str(), ";#it{p_{T, rec}} (GeV/#it{c});#it{p_{T, rec}} - #it{p_{T, gen}}(GeV/#it{c})", kTH2F, {{100, 0., 5.0}, {100, -2.5, 2.5}}); + h.dcaxyDcazToPt = reg.add( (dir + "/dcaxy_dcaz_to_pt").c_str(), "DCA_{xy} vs DCA_{z} vs p_{T};DCA_{xy} (cm);DCA_{z} (cm);p_{T} (GeV/#it{c})", kTH3F, @@ -187,7 +192,7 @@ struct AntitritonAnalysis { {101, -0.5, 0.5}, // y axis: DCA_z {20, 0., 5.0} // z axis: pT }); - h.dcaxy_to_dcaz = reg.add( + h.dcaxyToDcaz = reg.add( (dir + "/dcaxy_to_dcaz").c_str(), "DCA_{z} vs DCA_{xy};DCA_{xy} (cm);DCA_{z} (cm);Counts", kTH2F, @@ -198,7 +203,7 @@ struct AntitritonAnalysis { h.origin = reg.add((dir + "/origin").c_str(), "MC origin;origin (-1: unmatched, 0: primary, 1: weak decay, 2: material);Entries", kTH1F, {{4, -1.5, 2.5}}); if (pdgForPid != 0) { - h.TOFoverTPC = reg.add((dir + Form("/TOFoverTPC_PDG%i", pdgForPid)).c_str(), "n#sigma_{TOF};n#sigma_{TPC};", kTH2F, {{100, -10., 10.}, {100, -10., 10.}}); + h.tofOverTPC = reg.add((dir + Form("/TOFoverTPC_PDG%i", pdgForPid)).c_str(), "n#sigma_{TOF};n#sigma_{TPC};", kTH2F, {{100, -10., 10.}, {100, -10., 10.}}); h.nsigmaITS = reg.add((dir + Form("/nsigmaITS_PDG%i", pdgForPid)).c_str(), Form("n#sigma_{ITS};p (GeV/#it{c});n#sigma_{ITS}"), kTH2F, {{100, 0., 5.}, {100, -10., 10.}}); h.nsigmaTPC = reg.add((dir + Form("/nsigmaTPC_PDG%i", pdgForPid)).c_str(), Form("n#sigma_{TPC};p (GeV/#it{c});n#sigma_{TPC}"), kTH2F, {{100, 0., 5.}, {100, -10., 10.}}); h.nsigmaTOF = reg.add((dir + Form("/nsigmaTOF_PDG%i", pdgForPid)).c_str(), Form("n#sigma_{TOF};p (GeV/#it{c});n#sigma_{TOF}"), kTH2F, {{100, 0., 5.}, {100, -10., 10.}}); @@ -208,7 +213,7 @@ struct AntitritonAnalysis { } template - static float getMTOF(const TrackType& track) + static float getMassTOF(const TrackType& track) { const float beta = track.beta(); if (beta <= 0.f || beta >= 1.f) { @@ -220,45 +225,45 @@ struct AntitritonAnalysis { template void fillHistSet(HistSet& h, const TrackType& track, int pdg) { - const float mass = kMassTriton; - const auto y = static_cast(RecoDecay::y(std::array{track.px(), track.py(), track.pz()}, mass)); + const auto y = static_cast(RecoDecay::y(std::array{track.px(), track.py(), track.pz()}, particleMass)); h.eta->Fill(track.eta()); - h.eta_to_y->Fill(track.eta(), y); + h.etaToY->Fill(track.eta(), y); h.y->Fill(y); h.phi->Fill(track.phi()); h.p->Fill(track.p()); h.pt->Fill(track.pt()); - h.dcaxy_to_p->Fill(track.p(), track.dcaXY()); - h.dcaxy_to_pt->Fill(track.pt(), track.dcaXY()); - h.dcaz_to_p->Fill(track.p(), track.dcaZ()); - h.dcaz_to_pt->Fill(track.pt(), track.dcaZ()); - h.dcaxy_dcaz_to_pt->Fill(track.dcaXY(), track.dcaZ(), track.pt()); - h.dcaxy_to_dcaz->Fill(track.dcaXY(), track.dcaZ()); - h.TPCClusters->Fill(track.tpcNClsFound()); - h.ITSClusters->Fill(track.itsNCls()); + h.dcaxyToP->Fill(track.p(), track.dcaXY()); + h.dcaxyToPt->Fill(track.pt(), track.dcaXY()); + h.dcazToP->Fill(track.p(), track.dcaZ()); + h.dcazToPt->Fill(track.pt(), track.dcaZ()); + h.dcaxyDcazToPt->Fill(track.dcaXY(), track.dcaZ(), track.pt()); + h.dcaxyToDcaz->Fill(track.dcaXY(), track.dcaZ()); + h.tpcClusters->Fill(track.tpcNClsFound()); + h.itsClusters->Fill(track.itsNCls()); h.nsigmaITS->Fill(track.p(), o2::aod::singletrackselector::getITSNsigma(track, pdg)); h.nsigmaTPC->Fill(track.p(), o2::aod::singletrackselector::getTPCNsigma(track, pdg)); h.nsigmaTOF->Fill(track.p(), o2::aod::singletrackselector::getTOFNsigma(track, pdg)); - h.TOFoverTPC->Fill(o2::aod::singletrackselector::getTPCNsigma(track, pdg), o2::aod::singletrackselector::getTOFNsigma(track, pdg)); + h.tofOverTPC->Fill(o2::aod::singletrackselector::getTPCNsigma(track, pdg), o2::aod::singletrackselector::getTOFNsigma(track, pdg)); } template void fillHistSetExtra(HistSet& h, const TrackType& track) { - h.TPCSignal->Fill(track.tpcInnerParam(), track.tpcSignal()); - h.TOFSignal->Fill(track.p(), track.beta()); - h.mTOF->Fill(track.pt(), getMTOF(track)); + h.tpcSignal->Fill(track.tpcInnerParam(), track.tpcSignal()); + h.tofSignal->Fill(track.p(), track.beta()); + h.massTOF->Fill(track.pt(), getMassTOF(track)); h.innerParamToP->Fill(track.p(), track.tpcInnerParam() / track.p()); - if constexpr (HasMC) - h.PtGenPtRec->Fill(track.pt(), track.pt() - track.pt_MC()); + if constexpr (HasMC) { + h.ptGenPtRec->Fill(track.pt(), track.pt() - track.pt_MC()); + } } template - void fillSet(HistSet& Set, HistSet& mcSet, const TrackType& track, int pdg) + void fillSet(HistSet& set, HistSet& mcSet, const TrackType& track, int pdg) { - fillHistSet(Set, track, pdg); + fillHistSet(set, track, pdg); if constexpr (FillExtra) { - fillHistSetExtra(Set, track); + fillHistSetExtra(set, track); } if constexpr (HasMC) { @@ -275,25 +280,25 @@ struct AntitritonAnalysis { void init(o2::framework::InitContext&) { - if (isMC.value) + if (isMC.value) { o2::aod::ITSResponse::setMCDefaultParameters(); // set MC parametrisation for the ITS PID + } - ITScuts = std::make_pair(particlePDG.value, itsNSigma); - TPCcuts = std::make_pair(particlePDG.value, tpcNSigma); - TOFcuts = std::make_pair(particlePDG.value, tofNSigma); + particleMass = static_cast(pdgDB->Mass(particlePDG.value)); - int N = static_cast(dcaBinning.value[0]); // number of bins -- must be odd otherwise will be increased by 1 - if (N % 2 != 1) { - N += 1; - } + itsCuts = std::make_pair(particlePDG.value, itsNSigma); + tpcCuts = std::make_pair(particlePDG.value, tpcNSigma); + tofCuts = std::make_pair(particlePDG.value, tofNSigma); - std::unique_ptr dca_bins; - if (static_cast(dcaBinning.value[2]) != 1.0) { - dca_bins = calc_var_bins(N + 1, dcaBinning.value[1], static_cast(dcaBinning.value[2])); - } else { - dca_bins = calc_const_bins(N, -dcaBinning.value[1], dcaBinning.value[1]); + int nBins = static_cast(dcaBinning.value[0]); // number of bins -- must be odd otherwise will be increased by 1 + if ((nBins & 1) == 0) { // bin count must be odd + nBins += 1; } - auto const_bins_p = calc_const_bins(100, 0., 5.0); + + auto dcaBins = (static_cast(dcaBinning.value[2]) != 1.0) + ? calc_var_bins(nBins + 1, dcaBinning.value[1], static_cast(dcaBinning.value[2])) + : calc_const_bins(nBins, -dcaBinning.value[1], dcaBinning.value[1]); + auto constBinsP = calc_const_bins(100, 0., 5.0); hSets.resize(stageDirs.size()); hSetsTrue.resize(stageDirs.size()); @@ -321,24 +326,33 @@ struct AntitritonAnalysis { fillSet(hSets[1][signIdx], hSetsTrue[1][signIdx], track, particlePDG.value); // nocuts } for (const auto& collision : collisions) { - if (removeSameBunchPileup && !collision.isNoSameBunchPileup()) + if (removeSameBunchPileup && !collision.isNoSameBunchPileup()) { continue; - if (requestGoodZvtxFT0vsPV && !collision.isGoodZvtxFT0vsPV()) + } + if (requestGoodZvtxFT0vsPV && !collision.isGoodZvtxFT0vsPV()) { continue; - if (requestVertexITSTPC && !collision.isVertexITSTPC()) + } + if (requestVertexITSTPC && !collision.isVertexITSTPC()) { continue; - if (requestVertexTOFmatched > collision.isVertexTOForTRDmatched()) + } + if (requestVertexTOFmatched > collision.isVertexTOForTRDmatched()) { continue; - if (requestNoCollInTimeRangeStandard && !collision.noCollInTimeRangeStandard()) + } + if (requestNoCollInTimeRangeStandard && !collision.noCollInTimeRangeStandard()) { continue; - if (requestIsGoodITSLayersAll && !collision.isGoodITSLayersAll()) + } + if (requestIsGoodITSLayersAll && !collision.isGoodITSLayersAll()) { continue; - if (collision.multPerc() < centCut.value.first || collision.multPerc() >= centCut.value.second) + } + if (collision.multPerc() < centCut.value.first || collision.multPerc() >= centCut.value.second) { continue; - if (collision.hadronicRate() < irCut.value.first || collision.hadronicRate() >= irCut.value.second) + } + if (collision.hadronicRate() < irCut.value.first || collision.hadronicRate() >= irCut.value.second) { continue; - if (collision.occupancy() < occupancyCut.value.first || collision.occupancy() >= occupancyCut.value.second) + } + if (collision.occupancy() < occupancyCut.value.first || collision.occupancy() >= occupancyCut.value.second) { continue; + } registry.fill(HIST("posZ"), collision.posZ()); registry.fill(HIST("mult"), collision.mult()); @@ -350,60 +364,76 @@ struct AntitritonAnalysis { const auto& coll = track.template singleCollSel_as(); const int signIdx = (-track.sign() + 1) / 2; // 0: triton, 1: antitriton - if (removeSameBunchPileup && !coll.isNoSameBunchPileup()) + if (removeSameBunchPileup && !coll.isNoSameBunchPileup()) { continue; - if (requestGoodZvtxFT0vsPV && !coll.isGoodZvtxFT0vsPV()) + } + if (requestGoodZvtxFT0vsPV && !coll.isGoodZvtxFT0vsPV()) { continue; - if (requestVertexITSTPC && !coll.isVertexITSTPC()) + } + if (requestVertexITSTPC && !coll.isVertexITSTPC()) { continue; - if (requestVertexTOFmatched > coll.isVertexTOForTRDmatched()) + } + if (requestVertexTOFmatched > coll.isVertexTOForTRDmatched()) { continue; - if (requestNoCollInTimeRangeStandard && !coll.noCollInTimeRangeStandard()) + } + if (requestNoCollInTimeRangeStandard && !coll.noCollInTimeRangeStandard()) { continue; - if (requestIsGoodITSLayersAll && !coll.isGoodITSLayersAll()) + } + if (requestIsGoodITSLayersAll && !coll.isGoodITSLayersAll()) { continue; - if (std::fabs(coll.posZ()) > vertexZ) + } + if (std::fabs(coll.posZ()) > vertexZ) { continue; - if (coll.multPerc() < centCut.value.first || coll.multPerc() >= centCut.value.second) + } + if (coll.multPerc() < centCut.value.first || coll.multPerc() >= centCut.value.second) { continue; - if (coll.hadronicRate() < irCut.value.first || coll.hadronicRate() >= irCut.value.second) + } + if (coll.hadronicRate() < irCut.value.first || coll.hadronicRate() >= irCut.value.second) { continue; - if (coll.occupancy() < occupancyCut.value.first || coll.occupancy() >= occupancyCut.value.second) + } + if (coll.occupancy() < occupancyCut.value.first || coll.occupancy() >= occupancyCut.value.second) { continue; - if (track.tpcFractionSharedCls() > maxTpcFractionSharedCls) + } + if (track.tpcFractionSharedCls() > maxTpcFractionSharedCls) { continue; - if (track.itsNCls() < minItsNCls) + } + if (track.itsNCls() < minItsNCls) { continue; - if (std::fabs(track.dcaXY()) > dcaXY.value[0] + dcaXY.value[1] * std::pow(track.pt(), dcaXY.value[2])) + } + if (std::fabs(track.dcaXY()) > dcaXY.value[0] + dcaXY.value[1] * std::pow(track.pt(), dcaXY.value[2])) { continue; - if (std::fabs(track.dcaZ()) > dcaZ.value[0] + dcaZ.value[1] * std::pow(track.pt(), dcaZ.value[2])) + } + if (std::fabs(track.dcaZ()) > dcaZ.value[0] + dcaZ.value[1] * std::pow(track.pt(), dcaZ.value[2])) { continue; + } - if (o2::aod::singletrackselector::ITSselection(track, ITScuts)) { + if (o2::aod::singletrackselector::ITSselection(track, itsCuts)) { fillSet(hSets[2][signIdx], hSetsTrue[2][signIdx], track, particlePDG.value); // ITSCuts } - if (o2::aod::singletrackselector::TPCselection(track, TPCcuts, itsNSigma.value)) { + if (o2::aod::singletrackselector::TPCselection(track, tpcCuts, itsNSigma.value)) { fillSet(hSets[3][signIdx], hSetsTrue[3][signIdx], track, particlePDG.value); // TPCCuts } - if (o2::aod::singletrackselector::TOFselection(track, TOFcuts, tpcNSigmaResidual.value)) { + if (o2::aod::singletrackselector::TOFselection(track, tofCuts, tpcNSigmaResidual.value)) { fillSet(hSets[4][signIdx], hSetsTrue[4][signIdx], track, particlePDG.value); // TOFCuts } - if (o2::aod::singletrackselector::TPCselection(track, TPCcuts, itsNSigma.value)) { + if (o2::aod::singletrackselector::TPCselection(track, tpcCuts, itsNSigma.value)) { fillSet(hSets[5][signIdx], hSetsTrue[5][signIdx], track, particlePDG.value); // ITSTPC } const bool pidOk = (track.p() < pidTrshld) - ? o2::aod::singletrackselector::TPCselection(track, TPCcuts, itsNSigma.value) + ? o2::aod::singletrackselector::TPCselection(track, tpcCuts, itsNSigma.value) : o2::aod::singletrackselector::TPCselection(track, std::make_pair(particlePDG.value, tpcNSigmaResidual.value), tpcNSigmaResidual.value); - if (!pidOk) + if (!pidOk) { continue; - if (std::fabs(static_cast(RecoDecay::y(std::array{track.px(), track.py(), track.pz()}, kMassTriton))) > eta) + } + if (std::fabs(static_cast(RecoDecay::y(std::array{track.px(), track.py(), track.pz()}, particleMass))) > y) { continue; + } fillSet(hSets[6][signIdx], hSetsTrue[6][signIdx], track, particlePDG.value); // PIDcuts if constexpr (FillExtra) { - if (track.p() >= massCuttrshld && (getMTOF(track) <= tofMass.value[0] || getMTOF(track) >= tofMass.value[1])) { + if (track.p() >= massCuttrshld && (getMassTOF(track) <= tofMass.value[0] || getMassTOF(track) >= tofMass.value[1])) { continue; } } @@ -416,8 +446,9 @@ struct AntitritonAnalysis { break; } } - if (rejectedByPDG) + if (rejectedByPDG) { continue; + } fillSet(hSets[8][signIdx], hSetsTrue[8][signIdx], track, particlePDG.value); // rd if (getITSNsigma(track, particlePDG.value) <= itsNsigNL.value[0] + itsNsigNL.value[1] * track.p()) { From 963093b5194c1caa358d32ae682419107ee389f1 Mon Sep 17 00:00:00 2001 From: Nikita Gladin Date: Mon, 27 Jul 2026 04:32:58 +0200 Subject: [PATCH 5/6] PWGLF antitriton shadowing fix --- PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx b/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx index 7e40b097951..d597a774c5d 100644 --- a/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx +++ b/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx @@ -225,10 +225,10 @@ struct AntitritonAnalysis { template void fillHistSet(HistSet& h, const TrackType& track, int pdg) { - const auto y = static_cast(RecoDecay::y(std::array{track.px(), track.py(), track.pz()}, particleMass)); + const auto rapidity = static_cast(RecoDecay::y(std::array{track.px(), track.py(), track.pz()}, particleMass)); h.eta->Fill(track.eta()); - h.etaToY->Fill(track.eta(), y); - h.y->Fill(y); + h.etaToY->Fill(track.eta(), rapidity); + h.y->Fill(rapidity); h.phi->Fill(track.phi()); h.p->Fill(track.p()); h.pt->Fill(track.pt()); From 35417107763d968c668ca4118d4c357f37110d3d Mon Sep 17 00:00:00 2001 From: Nikita Gladin Date: Mon, 27 Jul 2026 09:53:31 +0200 Subject: [PATCH 6/6] PWGLF antitriton pdgDB usage fix --- PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx b/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx index d597a774c5d..6bfa837caaa 100644 --- a/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx +++ b/PWGLF/Tasks/Nuspex/antitritonAnalysis.cxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -60,7 +61,7 @@ struct AntitritonAnalysis { HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry registryTrue{"registryTrue", {}, OutputObjHandlingPolicy::AnalysisObject}; - Service pdgDB; + Service pdgDB{}; float particleMass = 0.f; Configurable isMC{"isMC", false, ""};